[IMP] tests: add generic Basecase.start for patch

Using patcher.start() can easily lead to incorrect cleanup.
-> after a copy paste, patcher is working, but stop is forgotten
-> stop is present, but won't be called if something fails during the
test

This commit add an utility `start(patcher)` to always have the add
cleanup.

Using a standard way to start the patcher with an automated addCleanup
should prevent this kind of mistake. This is why this commit also
replaces all valid patch.start() (followed immediately by a addCleanup)

closes odoo/odoo#102873

X-original-commit: 7d5a193d86316965a0908c65cfacfb607dc3f3ad
Related: odoo/enterprise#32618
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
This commit is contained in:
Xavier-Do
2022-10-10 16:11:01 +02:00
parent ddfae4b760
commit 503ed05029
19 changed files with 40 additions and 74 deletions
+1 -4
View File
@@ -53,11 +53,8 @@ class AccountPaymentCommon(PaymentCommon, AccountTestInvoicingCommon):
})
def setUp(self):
self.enable_reconcile_after_done_patcher = False
super().setUp()
# Disable _reconcile_after_done patcher
self.reconcile_after_done_patcher.stop()
self.is_patcher_started = False
#=== Utils ===#
@classmethod
+1 -2
View File
@@ -43,8 +43,7 @@ class WebsocketCase(common.HttpCase):
'_serve_forever',
wraps=_mocked_serve_forever
)
self._serve_forever_patch.start()
self.addCleanup(self._serve_forever_patch.stop)
self.startPatcher(self._serve_forever_patch)
def tearDown(self):
self._close_websockets()
+1 -6
View File
@@ -574,12 +574,7 @@ class TestLeadConvertCommon(TestCrmCommon):
cls.lead_1.write({'date_open': Datetime.from_string('2020-01-15 11:30:00')})
cls.crm_lead_dt_patcher = patch('odoo.addons.crm.models.crm_lead.fields.Datetime', wraps=Datetime)
cls.crm_lead_dt_mock = cls.crm_lead_dt_patcher.start()
@classmethod
def tearDownClass(cls):
cls.crm_lead_dt_patcher.stop()
super(TestLeadConvertCommon, cls).tearDownClass()
cls.crm_lead_dt_mock = cls.startClassPatcher(cls.crm_lead_dt_patcher)
@classmethod
def _switch_to_multi_membership(cls):
@@ -79,7 +79,7 @@ class TestKarmaTrackingCommon(common.TransactionCase):
def test_consolidation_cron(self):
self.patcher = patch('odoo.addons.gamification.models.gamification_karma_tracking.fields.Date', wraps=fields.Date)
self.mock_datetime = self.patcher.start()
self.mock_datetime = self.startPatcher(self.patcher)
self.mock_datetime.today.return_value = date(self.test_date.year, self.test_date.month + 1, self.test_date.day)
self._create_trackings(self.test_user, 20, 2, self.test_date, days_delta=30)
@@ -97,8 +97,6 @@ class TestKarmaTrackingCommon(common.TransactionCase):
])
self.assertEqual(len(unconsolidated), 6) # 5 for test user 2, 1 for test user
self.patcher.stop()
def test_consolidation_monthly(self):
Tracking = self.env['gamification.karma.tracking']
base_test_user_karma = self.test_user.karma
@@ -204,7 +202,7 @@ class TestComputeRankCommon(common.TransactionCase):
pass
patch_email = patch('odoo.addons.mail.models.mail_template.MailTemplate.send_mail', _patched_send_mail)
patch_email.start()
cls.startClassPatcher(patch_email)
cls.users = cls.env['res.users']
for k in range(-5, 1030, 30):
@@ -236,8 +234,6 @@ class TestComputeRankCommon(common.TransactionCase):
'karma_min': 1000,
})
patch_email.stop()
def test_00_initial_compute(self):
self.assertEqual(len(self.users), 35)
@@ -291,10 +287,9 @@ class TestComputeRankCommon(common.TransactionCase):
number_of_users = len(_self & self.users)
patch_bulk = patch('odoo.addons.gamification.models.res_users.Users._recompute_rank', _patched_recompute_rank)
patch_bulk.start()
self.startPatcher(patch_bulk)
self.rank_3.karma_min = 700
self.assertEqual(number_of_users, 7, "Should just recompute for the 7 users between 500 and 700")
patch_bulk.stop()
def test_03_test_bulk_call(self):
self.assertEqual(len(self.users), 35)
@@ -303,7 +298,7 @@ class TestComputeRankCommon(common.TransactionCase):
raise
patch_bulk = patch('odoo.addons.gamification.models.res_users.Users._recompute_rank_bulk', _patched_check_in_bulk)
patch_bulk.start()
self.startPatcher(patch_bulk)
# call on 5 users should not trigger the bulk function
self.users[0:5]._recompute_rank()
@@ -312,4 +307,3 @@ class TestComputeRankCommon(common.TransactionCase):
with self.assertRaises(Exception):
self.users[0:50]._recompute_rank()
patch_bulk.stop()
+1 -2
View File
@@ -18,8 +18,7 @@ class MockLinkTracker(common.BaseCase):
return "Test_TITLE"
link_tracker_title_patch = patch('odoo.addons.link_tracker.models.link_tracker.LinkTracker._get_title_from_url', wraps=_get_title_from_url)
link_tracker_title_patch.start()
self.addCleanup(link_tracker_title_patch.stop)
self.startPatcher(link_tracker_title_patch)
def _get_href_from_anchor_id(self, body, anchor_id):
""" Parse en html body to find the href of an element given its ID. """
+3 -8
View File
@@ -91,22 +91,17 @@ class PaymentCommon(TransactionCase):
account_payment_module = cls.env['ir.module.module']._get('account_payment')
cls.account_payment_installed = account_payment_module.state in ('installed', 'to upgrade')
cls.enable_reconcile_after_done_patcher = True
def setUp(self):
def stop_patcher_without_fail():
if self.is_patcher_started:
self.reconcile_after_done_patcher.stop()
super().setUp()
if self.account_payment_installed:
if self.account_payment_installed and self.enable_reconcile_after_done_patcher:
# disable account payment generation if account_payment is installed
# because the accounting setup of providers is not managed in this common
self.reconcile_after_done_patcher = patch(
'odoo.addons.account_payment.models.payment_transaction.PaymentTransaction._reconcile_after_done',
)
self.reconcile_after_done_patcher.start()
self.is_patcher_started = True
self.addCleanup(stop_patcher_without_fail)
self.startPatcher(self.reconcile_after_done_patcher)
#=== Utils ===#
@@ -274,7 +274,7 @@ class TestPurchaseLeadTime(PurchaseTestCommon):
})
company.write({'po_lead': 0.00})
self.patcher = patch('odoo.addons.stock.models.stock_orderpoint.fields.Date', wraps=fields.Date)
self.mock_date = self.patcher.start()
self.mock_date = self.startPatcher(self.patcher)
vendor = self.env['res.partner'].create({
'name': 'Colruyt'
@@ -360,7 +360,6 @@ class TestPurchaseLeadTime(PurchaseTestCommon):
new_order = po_line.order_id.sorted('date_order')[-1]
self.assertEqual(fields.Date.to_date(new_order.date_order), fields.Date.today() + timedelta(days=2))
self.assertEqual(new_order.order_line.product_uom_qty, 5.0)
self.patcher.stop()
def test_supplier_lead_time(self):
""" Basic stock configuration and a supplier with a minimum qty and a lead time """
@@ -692,8 +692,8 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
patch('odoo.fields.Date.context_today', _today),
]
for p in patchers:
p.start()
for patcher in patchers:
self.startPatcher(patcher)
# Proceed
po = self.env['purchase.order'].create({
@@ -755,9 +755,6 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
inv.action_post()
for p in patchers:
p.stop()
move_lines = inv.line_ids
self.assertEqual(len(move_lines), 3)
@@ -867,8 +864,8 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
patch('odoo.fields.Datetime.now', _now),
]
for p in patchers:
p.start()
for patcher in patchers:
self.startPatcher(patcher)
# Proceed
po = self.env['purchase.order'].create({
@@ -921,9 +918,6 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
inv.action_post()
for p in patchers:
p.stop()
self.assertRecordValues(inv.line_ids, [
# pylint: disable=C0326
{'balance': 15.0, 'amount_currency': 30.0, 'account_id': self.stock_input_account.id},
@@ -221,21 +221,19 @@ record['name'] = record.name + 'X'""",
patch('odoo.addons.mail.models.mail_template.MailTemplate.send_mail', _patched_send_mail),
]
patchers[0].start()
self.startPatcher(patchers[0])
lead = self.create_lead()
self.assertFalse(lead.priority)
self.assertFalse(lead.deadline)
patchers[1].start()
self.startPatcher(patchers[1])
lead.write({'priority': True})
self.assertTrue(lead.priority)
self.assertTrue(lead.deadline)
for patcher in patchers:
patcher.stop()
self.assertEqual(send_mail_count, 1)
+1 -5
View File
@@ -58,11 +58,7 @@ class TestStaticInheritanceCommon(odoo.tests.TransactionCase):
""",
}
self._patch = patch.object(WebAsset, '_fetch_content', lambda asset: self.template_files[asset.url])
self._patch.start()
def tearDown(self):
super().tearDown()
self._patch.stop()
self.startPatcher(self._patch)
def renderBundle(self, debug=False):
files = []
+1 -2
View File
@@ -39,8 +39,7 @@ class TestDatabaseOperations(BaseCase):
self.verify_admin_password_patcher = patch(
'odoo.tools.config.verify_admin_password', self.password.__eq__,
)
self.verify_admin_password_patcher.start()
self.addCleanup(self.verify_admin_password_patcher.stop)
self.startPatcher(self.verify_admin_password_patcher)
self.db_name = config['db_name']
self.assertTrue(self.db_name)
+1 -3
View File
@@ -19,8 +19,7 @@ class ProfilingHttpCase(HttpCase):
# its actual cursor), which prevents the profiling data from being
# committed for real.
cls.patcher = patch('odoo.sql_db.db_connect', return_value=cls.registry)
cls.patcher.start()
cls.addClassCleanup(cls.patcher.stop)
cls.startClassPatcher(cls.patcher)
def profile_rpc(self, params=None):
params = params or {}
@@ -37,7 +36,6 @@ class ProfilingHttpCase(HttpCase):
req.raise_for_status()
return req.json()
@tagged('post_install', '-at_install', 'profiling')
class TestProfilingWeb(ProfilingHttpCase):
def test_profiling_enabled(self):
+2 -4
View File
@@ -45,12 +45,10 @@ class TestConfiguratorCommon(odoo.tests.HttpCase):
iap_jsonrpc_mocked()
iap_patch = patch('odoo.addons.iap.tools.iap_tools.iap_jsonrpc', iap_jsonrpc_mocked_configurator)
iap_patch.start()
self.addCleanup(iap_patch.stop)
self.startPatcher(iap_patch)
patcher = patch('odoo.addons.website.models.ir_module_module.IrModuleModule._theme_upgrade_upstream', wraps=self._theme_upgrade_upstream)
patcher.start()
self.addCleanup(patcher.stop)
self.startPatcher(patcher)
@odoo.tests.common.tagged('post_install', '-at_install')
class TestConfiguratorTranslation(TestConfiguratorCommon):
@@ -34,8 +34,7 @@ class TestPartnerAssign(TransactionCase):
}.get(addr)
patcher = patch('odoo.addons.base_geolocalize.models.base_geocoder.GeoCoder.geo_find', wraps=geo_find)
patcher.start()
self.addCleanup(patcher.stop)
self.startPatcher(patcher)
def test_opportunity_count(self):
self.customer_uk.write({
+1 -2
View File
@@ -15,8 +15,7 @@ class TestUi(odoo.tests.HttpCase):
return 'Contact Us | My Website'
patcher = patch('odoo.addons.link_tracker.models.link_tracker.LinkTracker._get_title_from_url', wraps=_get_title_from_url)
patcher.start()
self.addCleanup(patcher.stop)
self.startPatcher(patcher)
def test_01_test_ui(self):
self.env['link.tracker'].search_or_create({
@@ -103,8 +103,7 @@ class TestWebsitePriceList(TransactionCase):
'current_pl': False,
}
patcher = patch('odoo.addons.website_sale.models.website.Website.get_pricelist_available', wraps=self._get_pricelist_available)
patcher.start()
self.addCleanup(patcher.stop)
self.startPatcher(patcher)
# Mock nedded because request.session doesn't exist during test
def _get_pricelist_available(self, show_visible=False):
@@ -284,8 +283,7 @@ def simulate_frontend_context(self, website_id=1):
def get_request_website():
return self.env['website'].browse(website_id)
patcher = patch('odoo.addons.website.models.ir_http.get_request_website', wraps=get_request_website)
patcher.start()
self.addCleanup(patcher.stop)
self.startPatcher(patcher)
@tagged('post_install', '-at_install')
+1 -2
View File
@@ -19,8 +19,7 @@ class TestModuleManifest(BaseCase):
cls.addons_path = cls._tmp_dir.name
patcher = patch.object(odoo.addons, '__path__', [cls.addons_path])
patcher.start()
cls.addClassCleanup(patcher.stop)
cls.startClassPatcher(patcher)
def setUp(self):
self.module_root = tempfile.mkdtemp(prefix='odoo-test-module-', dir=self.addons_path)
@@ -15,8 +15,7 @@ class TestPopulate(common.TransactionCase):
def setUp(self):
super(TestPopulate, self).setUp()
patcher = patch.object(self.cr, 'commit')
patcher.start()
self.addCleanup(patcher.stop)
self.startPatcher(patcher)
def test_dependency(self):
ordered_models = Populate._get_ordered_models(self.env, ['test.populate'])
+11
View File
@@ -465,6 +465,17 @@ class BaseCase(unittest.TestCase, metaclass=MetaCase):
patcher.start()
cls.addClassCleanup(patcher.stop)
def startPatcher(self, patcher):
mock = patcher.start()
self.addCleanup(patcher.stop)
return mock
@classmethod
def startClassPatcher(cls, patcher):
mock = patcher.start()
cls.addClassCleanup(patcher.stop)
return mock
@contextmanager
def with_user(self, login):
""" Change user for a given test, like with self.with_user() ... """