Coverage for adhoc-cicd-odoo-odoo / odoo / tests / loader.py: 98%
68 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-09 18:05 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-09 18:05 +0000
1import importlib
2import importlib.util
3import inspect
4import logging
5import sys
6from pathlib import Path
7from unittest import case
9from .. import tools
10from .tag_selector import TagsSelector
11from .suite import OdooSuite
12from .result import OdooTestResult
15_logger = logging.getLogger(__name__)
18def get_module_test_cases(module):
19 """Return a suite of all test cases contained in the given module"""
20 for obj in module.__dict__.values():
21 if not isinstance(obj, type):
22 continue
23 if not issubclass(obj, case.TestCase):
24 continue
25 if obj.__module__ != module.__name__:
26 continue
28 test_case_class = obj
29 test_cases = test_case_class.__dict__.items()
30 if getattr(test_case_class, 'allow_inherited_tests_method', False):
31 # keep iherited method for specific classes.
32 # This is likely to be removed once a better solution is found
33 test_cases = inspect.getmembers(test_case_class, callable)
34 else:
35 # sort test case to keep the initial behaviour.
36 # This is likely to be removed in the future
37 test_cases = sorted(test_cases, key=lambda pair: pair[0])
39 for method_name, method in test_cases:
40 if not callable(method):
41 continue
42 if not method_name.startswith('test'):
43 continue
44 yield test_case_class(method_name)
47def get_test_modules(module):
48 """ Return a list of module for the addons potentially containing tests to
49 feed get_module_test_cases() """
50 results = _get_tests_modules(importlib.util.find_spec(f'odoo.addons.{module}'))
51 results += list(_get_upgrade_test_modules(module))
53 return results
56def _get_tests_modules(mod):
57 spec = importlib.util.find_spec('.tests', mod.name)
58 if not spec:
59 return []
61 tests_mod = importlib.import_module(spec.name)
62 return [
63 mod_obj
64 for name, mod_obj in inspect.getmembers(tests_mod, inspect.ismodule)
65 if name.startswith('test_')
66 ]
69def _get_upgrade_test_modules(module):
70 upgrade_modules = (
71 f"odoo.upgrade.{module}",
72 f"odoo.addons.{module}.migrations",
73 f"odoo.addons.{module}.upgrades",
74 )
75 for module_name in upgrade_modules:
76 if not importlib.util.find_spec(module_name):
77 continue
79 upg = importlib.import_module(module_name)
80 for path in map(Path, upg.__path__):
81 for test in path.glob("tests/test_*.py"):
82 spec = importlib.util.spec_from_file_location(f"{upg.__name__}.tests.{test.stem}", test)
83 if not spec: 83 ↛ 84line 83 didn't jump to line 84 because the condition on line 83 was never true
84 continue
85 pymod = importlib.util.module_from_spec(spec)
86 sys.modules[spec.name] = pymod
87 spec.loader.exec_module(pymod)
88 yield pymod
91def make_suite(module_names, position='at_install'):
92 """ Creates a test suite for all the tests in the specified modules,
93 filtered by the provided ``position`` and the current test tags
95 :param list[str] module_names: modules to load tests from
96 :param str position: "at_install" or "post_install"
97 """
98 config_tags = TagsSelector(tools.config['test_tags'])
99 position_tag = TagsSelector(position)
100 tests = (
101 t
102 for module_name in module_names
103 for m in get_test_modules(module_name)
104 for t in get_module_test_cases(m)
105 if position_tag.check(t) and config_tags.check(t)
106 )
107 return OdooSuite(sorted(tests, key=lambda t: getattr(t, 'test_sequence', 0)))
110def run_suite(suite, global_report=None):
111 # avoid dependency hell
112 from ..modules import module
113 module.current_test = True
115 results = OdooTestResult(global_report=global_report)
116 suite(results)
118 module.current_test = False
119 return results