Skip to content

Commit 0140c26

Browse files
committed
[FIX] Make pytest-odoo compatible with pytest-subtests and subTest context manager
1 parent ffdedcc commit 0140c26

File tree

5 files changed

+45
-43
lines changed

5 files changed

+45
-43
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: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
import subprocess
1111
import threading
1212
from contextlib import contextmanager
13-
from unittest import mock, TestCase as UnitTestTestCase
1413
from pathlib import Path
1514
from typing import Optional
15+
from unittest import TestCase as UnitTestTestCase
16+
from unittest import mock
1617

1718
import _pytest
1819
import _pytest.python
@@ -88,8 +89,8 @@ def pytest_cmdline_main(config):
8889
raise Exception(
8990
"please provide a database name in the Odoo configuration file"
9091
)
91-
disable_odoo_test_retry()
9292
support_subtest()
93+
disable_odoo_test_retry()
9394
monkey_patch_resolve_pkg_root_and_module_name()
9495
odoo.service.server.start(preload=[], stop=True)
9596
# odoo.service.server.start() modifies the SIGINT signal by its own
@@ -106,7 +107,6 @@ def pytest_cmdline_main(config):
106107
else:
107108
yield
108109

109-
110110
@pytest.fixture(scope="module", autouse=True)
111111
def load_http(request):
112112
if request.config.getoption("--odoo-http"):
@@ -153,7 +153,7 @@ def _worker_db_name():
153153
odoo.tools.config["db_name"] = original_db_name
154154
odoo.tools.config["dbfilter"] = f"^{original_db_name}$"
155155

156-
156+
157157
@pytest.fixture(scope='session', autouse=True)
158158
def load_registry():
159159
# Initialize the registry before running tests.
@@ -203,19 +203,6 @@ def resolve_pkg_root_and_module_name(
203203
_pytest.pathlib.resolve_pkg_root_and_module_name= resolve_pkg_root_and_module_name
204204

205205

206-
def disable_odoo_test_retry():
207-
"""Odoo BaseCase.run method overload TestCase.run and manage
208-
a retry mechanism that breaks using pytest launcher.
209-
Using `pytest-rerunfailures` we can use `--reruns` parameters
210-
if needs equivalent feature, so we remove such overload here.
211-
"""
212-
try:
213-
from odoo.tests import BaseCase
214-
del BaseCase.run
215-
except (ImportError, AttributeError):
216-
# Odoo <= 15.0
217-
pass
218-
219206
def support_subtest():
220207
"""Odoo from version 16.0 re-define its own TestCase.subTest context manager
221208
@@ -226,13 +213,26 @@ def support_subtest():
226213
try:
227214
from odoo.tests.case import TestCase
228215
TestCase.subTest = UnitTestTestCase.subTest
229-
230-
from odoo.tests.case import _Outcome
231-
_Outcome.result_supports_subtests = False
216+
TestCase.run = UnitTestTestCase.run
232217
except ImportError:
233218
# Odoo <= 15.0
234219
pass
235220

221+
222+
def disable_odoo_test_retry():
223+
"""Odoo BaseCase.run method overload TestCase.run and manage
224+
a retry mechanism that breaks using pytest launcher.
225+
Using `pytest-rerunfailures` we can use `--reruns` parameters
226+
if needs equivalent feature, so we remove such overload here.
227+
"""
228+
try:
229+
from odoo.tests import BaseCase
230+
del BaseCase.run
231+
except (ImportError, AttributeError):
232+
# Odoo <= 15.0
233+
pass
234+
235+
236236
def _find_manifest_path(collection_path: Path) -> Path:
237237
"""Try to locate an Odoo manifest file in the collection path."""
238238
# check if collection_path is an addon directory
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)