Skip to content

Commit 065742a

Browse files
committed
Make pytest-odoo compatible with pytest-subtests
1 parent f7422e3 commit 065742a

File tree

5 files changed

+42
-41
lines changed

5 files changed

+42
-41
lines changed

README.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,5 @@ You can use the ``ODOO_RC`` environment variable using an odoo configuration fil
5353

5454
The plugin is also compatible with distributed run provided by the `pytest-xdist <https://pypi.org/project/pytest-xdist/>`_ library. When tests are distributed, a copy of the database is created for each worker at the start of the test session.
5555
This is useful to avoid concurrent access to the same database, which can lead to deadlocks. The provided database is therefore used only as template. At the end of the tests, all the created databases are dropped.
56+
57+
The plugin is also compatible with `pytest-subtests <https://pypi.org/project/pytest-subtests/>`_ library. When test use the `subTest` context manager you'll get a nice output for each sub-tests failing.

pytest_odoo.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ def pytest_cmdline_main(config):
8888
raise Exception(
8989
"please provide a database name in the Odoo configuration file"
9090
)
91-
disable_odoo_test_retry()
9291
support_subtest()
92+
disable_odoo_test_retry()
9393
monkey_patch_resolve_pkg_root_and_module_name()
9494
odoo.service.server.start(preload=[], stop=True)
9595
# odoo.service.server.start() modifies the SIGINT signal by its own
@@ -106,7 +106,6 @@ def pytest_cmdline_main(config):
106106
else:
107107
yield
108108

109-
110109
@pytest.fixture(scope="module", autouse=True)
111110
def load_http(request):
112111
if request.config.getoption("--odoo-http"):
@@ -203,6 +202,22 @@ def resolve_pkg_root_and_module_name(
203202
_pytest.pathlib.resolve_pkg_root_and_module_name= resolve_pkg_root_and_module_name
204203

205204

205+
def support_subtest():
206+
"""Odoo from version 16.0 re-define its own TestCase.subTest context manager
207+
208+
Odoo assume the usage of OdooTestResult which is not our case
209+
using with pytest-odoo. So this fallback to the unitest.TestCase.subTest
210+
Context manager
211+
"""
212+
try:
213+
from odoo.tests.case import TestCase
214+
TestCase.subTest = UnitTestTestCase.subTest
215+
TestCase.run = UnitTestTestCase.run
216+
except ImportError:
217+
# Odoo <= 15.0
218+
pass
219+
220+
206221
def disable_odoo_test_retry():
207222
"""Odoo BaseCase.run method overload TestCase.run and manage
208223
a retry mechanism that breaks using pytest launcher.
@@ -216,22 +231,6 @@ def disable_odoo_test_retry():
216231
# Odoo <= 15.0
217232
pass
218233

219-
def support_subtest():
220-
"""Odoo from version 16.0 re-define its own TestCase.subTest context manager
221-
222-
Odoo assume the usage of OdooTestResult which is not our case
223-
using with pytest-odoo. So this fallback to the unitest.TestCase.subTest
224-
Context manager
225-
"""
226-
try:
227-
from odoo.tests.case import TestCase
228-
TestCase.subTest = UnitTestTestCase.subTest
229-
230-
from odoo.tests.case import _Outcome
231-
_Outcome.result_supports_subtests = False
232-
except ImportError:
233-
# Odoo <= 15.0
234-
pass
235234

236235
def _find_manifest_path(collection_path: Path) -> Path:
237236
"""Try to locate an Odoo manifest file in the collection path."""
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
from . import case
2+
13
from unittest.mock import MagicMock
24
common = MagicMock()
3-
from . import case
45

56
class BaseCase(case.TestCase):
67

7-
def run(*args, **kwargs):
8+
def run(self, *args, **kwargs):
89
super().run(*args, **kwargs)
10+
self._call_something()
11+
12+
def _call_something(self):
13+
pass

tests/mock/odoo/odoo/tests/case.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33

44
class TestCase:
5-
5+
66
@contextlib.contextmanager
77
def subTest(self, **kwargs):
88
"""Simulate odoo TestCase.subTest from version 15.0"""
99

10+
def run(self, *args, **kwargs):
11+
self._call_a_method()
1012

11-
class _Outcome:
12-
pass
13+
def _call_a_method(self):
14+
pass

tests/test_pytest_odoo.py

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from contextlib import contextmanager
33
from pathlib import Path
44
from unittest import TestCase
5+
from unittest.mock import patch
56

67
from _pytest import pathlib as pytest_pathlib
78
from pytest_odoo import (
@@ -98,7 +99,9 @@ def restore_basecase_run():
9899
self.addCleanup(restore_basecase_run)
99100

100101
disable_odoo_test_retry()
101-
self.assertFalse(hasattr(BaseCase, "run"))
102+
with patch("odoo.tests.BaseCase._call_something") as mock:
103+
BaseCase().run()
104+
mock.assert_not_called()
102105

103106

104107
def test_disable_odoo_test_retry_ignore_run_doesnt_exists(self):
@@ -114,9 +117,10 @@ def restore_basecase_run():
114117
del BaseCase.run
115118

116119
disable_odoo_test_retry()
117-
self.assertFalse(hasattr(BaseCase, "run"))
118-
119120

121+
with patch("odoo.tests.BaseCase._call_something") as mock:
122+
BaseCase().run()
123+
mock.assert_not_called()
120124

121125
def test_import_error(self):
122126
from odoo import tests
@@ -135,30 +139,19 @@ def test_support_subtest(self):
135139
from odoo.tests import case
136140

137141
original_test_case = case.TestCase
138-
original_outcome = case._Outcome
139142

140143
def restore():
141144
case.TestCase = original_test_case
142-
case._Outcome = original_outcome
143145

144146
self.addCleanup(restore)
145147
support_subtest()
148+
146149
from odoo.tests import BaseCase
150+
from odoo.tests.case import TestCase as OdooTestCase
147151

152+
self.assertTrue(OdooTestCase.subTest is TestCase.subTest)
148153
self.assertTrue(BaseCase.subTest is TestCase.subTest)
149-
150-
def test_support_subtest_no_base_case(self):
151-
from odoo import tests
152-
153-
original_BaseCase = tests.BaseCase
154-
155-
def restore_basecase():
156-
tests.BaseCase = original_BaseCase
157-
158-
self.addCleanup(restore_basecase)
159-
160-
del tests.BaseCase
161-
support_subtest()
154+
self.assertTrue(OdooTestCase.run is TestCase.run)
162155

163156
def test_support_subtest_import_error(self):
164157
from odoo.tests import case

0 commit comments

Comments
 (0)