@@ -237,7 +237,7 @@ class OETestLoader(unittest.TestLoader):
pattern='*.py', top_level_dir=path)
big_suite.addTests(suite)
- cases = None
+ cases = list(self.tc._registry['cases'].values())
discover_classes = [clss for clss in decoratorClasses
if issubclass(clss, OETestDiscover)]
for clss in discover_classes:
@@ -246,7 +246,7 @@ class OETestLoader(unittest.TestLoader):
if self.modules_required:
self._required_modules_validation()
- return self.suiteClass(cases) if cases else big_suite
+ return self.suiteClass(cases)
def _filterModule(self, module):
if module.__name__ in sys.builtin_module_names:
@@ -6,6 +6,9 @@
#
import os
+import subprocess
+import sys
+import textwrap
import unittest
from common import setup_sys_path, TestBase
@@ -59,5 +62,25 @@ class TestLoader(TestBase):
msg = 'Expected modules from two different paths'
self.assertEqual(modules, expected_modules, msg=msg)
+ def test_flat_suite(self):
+ # The loaded suite must be a flat list of tests, which skipTests()
+ # relies on, even if no module registers a discovery decorator such as
+ # OETestDepends. Registering one is global so use a new process.
+ oeqa_lib = os.path.realpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../../'))
+ cases_path = os.path.join(self.cases_path, 'loader', 'valid')
+ script = textwrap.dedent("""
+ import logging, sys, unittest
+ sys.path.insert(0, %r)
+ from oeqa.core.context import OETestContext
+ from oeqa.core.decorator import decoratorClasses
+ tc = OETestContext({}, logging.getLogger('flat'))
+ tc.loadTests(%r)
+ assert not [c for c in decoratorClasses if c.__name__ == 'OETestDepends']
+ tc.skipTests(['another.AnotherTest.testAnother'])
+ print(' '.join(type(t).__name__ for t in tc.suites))
+ """) % (oeqa_lib, cases_path)
+ output = subprocess.check_output([sys.executable, '-c', script], text=True)
+ self.assertEqual(output.split(), ['AnotherTest'])
+
if __name__ == '__main__':
unittest.main()
OETestLoader.discover() returned a flat suite of the loaded tests only when a discovery decorator class was registered, which happens as a side effect of some loaded module importing oeqa.core.decorator.depends. Otherwise it returned unittest's nested per module suites. skipTests() expects a flat suite, so with no module importing OETestDepends, as for the oe-core selftests on their own, --skip-tests failed with: AttributeError: 'TestSuite' object has no attribute 'id' Always return a flat suite, using the registered test cases in the order they were loaded when no discovery decorator reorders them, and add a test which runs without OETestDepends registered. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> --- meta/lib/oeqa/core/loader.py | 4 ++-- meta/lib/oeqa/core/tests/test_loader.py | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-)