summaryrefslogtreecommitdiff
path: root/odoo/addons/test_performance
diff options
context:
space:
mode:
authorRaphael Collet <rco@odoo.com>2017-09-11 09:55:00 +0200
committerRaphael Collet <rco@odoo.com>2017-09-12 17:16:24 +0200
commitee14025c52f1be273d06c7c05acbe24c71ac00a8 (patch)
tree03e77bcfb2fa239e4eeda01323b35bf4e9736aea /odoo/addons/test_performance
parentecb394710feeaa80213e330ad9cd21592b0ba439 (diff)
[REF] test_performance: improve cache warmup in test methods
Diffstat (limited to 'odoo/addons/test_performance')
-rw-r--r--odoo/addons/test_performance/tests/test_performance.py192
1 files changed, 99 insertions, 93 deletions
diff --git a/odoo/addons/test_performance/tests/test_performance.py b/odoo/addons/test_performance/tests/test_performance.py
index b13c21d1b16..175d320f92b 100644
--- a/odoo/addons/test_performance/tests/test_performance.py
+++ b/odoo/addons/test_performance/tests/test_performance.py
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from contextlib import contextmanager
+import functools
import logging
from odoo.tests.common import TransactionCase
@@ -9,14 +10,39 @@ from odoo.tests.common import TransactionCase
sql_logger = logging.getLogger('odoo.sql_db')
+def queryCount(count):
+ """ Decorate a method to check the number of queries it makes. """
+ def decorate(func):
+ @functools.wraps(func)
+ def wrapper(self):
+ # warm up the caches
+ self._round = False
+ func(self)
+ self.env.cache.invalidate()
+ # test for real, and check query count
+ self._round = True
+ self.resetQueryCount()
+ func(self)
+ self.assertLessEqual(self.cr.sql_log_count - self._count, count)
+
+ return wrapper
+
+ return decorate
+
+
class TestPerformance(TransactionCase):
- @contextmanager
- def assertMaxQueries(self, message, count):
- """ Check the number of queries made in this scope. """
- count0 = self.cr.sql_log_count
- yield
- count1 = self.cr.sql_log_count
- self.assertLessEqual(count1 - count0, count, message)
+
+ def resetQueryCount(self):
+ """ Reset the query counter. """
+ self._count = self.cr.sql_log_count
+
+ def str(self, value):
+ """ Return a value different from run to run. """
+ return value + 'z' if self._round else value
+
+ def int(self, value):
+ """ Return a value different from run to run. """
+ return value + 1 if self._round else value
@contextmanager
def logQueries(self):
@@ -30,132 +56,112 @@ class TestPerformance(TransactionCase):
self.cr.sql_log = sql_log
sql_logger.setLevel(level)
+ @queryCount(3)
def test_read_base(self):
- """ Check reading records. """
+ """ Read records. """
records = self.env['test_performance.base'].search([])
self.assertEqual(len(records), 5)
+ self.resetQueryCount()
# without cache
- with self.assertMaxQueries("Prefetch records", 3):
- for record in records:
- record.partner_id.country_id.name
+ for record in records:
+ record.partner_id.country_id.name
# with cache
- with self.assertMaxQueries("Read prefetched records", 0):
- for record in records:
- record.partner_id.country_id.name
+ for record in records:
+ record.partner_id.country_id.name
# value_pc must have been prefetched, too
- with self.assertMaxQueries("Read another field on prefetched records", 0):
- for record in records:
- record.value_pc
+ for record in records:
+ record.value_pc
+ @queryCount(3)
def test_read_mail(self):
- """ Check reading records inheriting from 'mail.thread'. """
+ """ Read records inheriting from 'mail.thread'. """
records = self.env['test_performance.mail'].search([])
self.assertEqual(len(records), 5)
+ self.resetQueryCount()
# without cache
- with self.assertMaxQueries("Prefetch records", 3):
- for record in records:
- record.partner_id.country_id.name
+ for record in records:
+ record.partner_id.country_id.name
# with cache
- with self.assertMaxQueries("Read prefetched records", 0):
- for record in records:
- record.partner_id.country_id.name
+ for record in records:
+ record.partner_id.country_id.name
# value_pc must have been prefetched, too
- with self.assertMaxQueries("Read another field on prefetched records", 0):
- for record in records:
- record.value_pc
+ for record in records:
+ record.value_pc
+ @queryCount(1)
def test_write_base(self):
- """ Check writing records. """
+ """ Write records (no recomputation). """
records = self.env['test_performance.base'].search([])
self.assertEqual(len(records), 5)
+ self.resetQueryCount()
- # warm up the caches
- records.write({'name': 'Start', 'value': 10})
-
- # write in batch, without recomputation
- with self.assertMaxQueries("Write in batch, no recomputation", 1):
- records.write({'name': 'X'})
+ records.write({'name': self.str('X')})
- # write one by one, without recomputation
- with self.assertMaxQueries("Write one by one, no recomputation", 5):
- for record in records:
- record.name = 'Y'
-
- # write in batch, with recomputation
- with self.assertMaxQueries("Write in batch, with recomputation", 3):
- records.write({'value': 20})
+ @queryCount(3)
+ def test_write_base_with_recomputation(self):
+ """ Write records (with recomputation). """
+ records = self.env['test_performance.base'].search([])
+ self.assertEqual(len(records), 5)
+ self.resetQueryCount()
- # write one by one, with recomputation
- with self.assertMaxQueries("Write one by one, with recomputation", 15):
- for record in records:
- record.value = 30
+ records.write({'value': self.int(20)})
+ @queryCount(7)
def test_write_mail(self):
- """ Check writing records inheriting from 'mail.thread'. """
+ """ Write records inheriting from 'mail.thread' (no recomputation). """
records = self.env['test_performance.mail'].search([])
self.assertEqual(len(records), 5)
+ self.resetQueryCount()
- # warm up the caches
- records.write({'value': 0})
- records.write({'name': '0'})
-
- # write in batch, without recomputation
- with self.assertMaxQueries("Write in batch, no recomputation", 3):
- records.write({'name': 'X'})
+ records.write({'name': self.str('X')})
- # write one by one, without recomputation
- with self.assertMaxQueries("Write one by one, no recomputation", 15):
- for record in records:
- record.name = 'Y'
+ @queryCount(9)
+ def test_write_mail_with_recomputation(self):
+ """ Write records inheriting from 'mail.thread' (with recomputation). """
+ records = self.env['test_performance.mail'].search([])
+ self.assertEqual(len(records), 5)
+ self.resetQueryCount()
- # write in batch, with recomputation
- with self.assertMaxQueries("Write in batch, with recomputation", 5):
- records.write({'value': 20})
+ records.write({'value': self.int(20)})
- # write one by one, with recomputation
- with self.assertMaxQueries("Write one by one, with recomputation", 25):
- for record in records:
- record.value = 30
+ @queryCount(45)
+ def test_write_mail_with_tracking(self):
+ """ Write records inheriting from 'mail.thread' (with field tracking). """
+ record = self.env['test_performance.mail'].search([], limit=1)
+ self.assertEqual(len(record), 1)
+ self.resetQueryCount()
- # write on a tracked field
- with self.assertMaxQueries("Write on a tracked field", 48):
- records[0].track = 'X'
+ record.track = self.str('X')
+ @queryCount(6)
def test_create_base(self):
- """ Check creating records. """
+ """ Create records. """
model = self.env['test_performance.base']
+ model.create({'name': self.str('X')})
- # warm up caches
- model.create({'name': 'X'})
-
- # create record without lines
- with self.assertMaxQueries("Create record without lines", 6):
- model.create({'name': 'X'})
-
- # create record with lines
- with self.assertMaxQueries("Create record with lines", 39):
- model.create({
- 'name': 'X',
- 'line_ids': [(0, 0, {'value': val}) for val in range(10)],
- })
+ @queryCount(38)
+ def test_create_base_with_lines(self):
+ """ Create records with lines. """
+ model = self.env['test_performance.base']
+ model.create({
+ 'name': self.str('Y'),
+ 'line_ids': [(0, 0, {'value': val}) for val in range(10)],
+ })
+ @queryCount(3)
def test_create_mail(self):
- """ Check creating records inheriting from 'mail.thread'. """
+ """ Create records inheriting from 'mail.thread' (without field tracking). """
model = self.env['test_performance.mail']
+ model.with_context(tracking_disable=True).create({'name': self.str('X')})
- # warm up caches
- model.create({'name': 'X'})
-
- # create without tracking changes
- with self.assertMaxQueries("Create record without tracking fields", 3):
- model.with_context(tracking_disable=True).create({'name': 'X'})
-
- # create with tracking changes
- with self.assertMaxQueries("Create record with tracking fields", 87):
- model.create({'name': 'X'})
+ @queryCount(87)
+ def test_create_mail_with_tracking(self):
+ """ Create records inheriting from 'mail.thread' (with field tracking). """
+ model = self.env['test_performance.mail']
+ model.create({'name': self.str('Y')})