From cb1ee13e9db185b39b0ab5f72247a9ead5be2d48 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Tue, 30 Jan 2024 15:54:22 -0500 Subject: [PATCH] twister: only parse specified tests when using --test Enhance the -s option of twister, used to point to a single scenario in a testsuite. - Now accept --scenario on the command line, --test still supported. - If no testsuite is provided, extract testsuite from scenario identifier and avoid parsing the whole tree if we only want to address one scenario in a testsuite. - If just the identifier of the scenario is provided to --test/--scenario option, try to find this as well, do not need the full path for that. Something like this is now possible: twister --scenario kernel.threads.init --list-tests twister -T --scenario kernel.threads.init --list-tests twister -T /kernel.threads.init --list-tests All should print the same output. Fixes #67307 Signed-off-by: Anas Nashif --- .../pylib/twister/twisterlib/environment.py | 16 ++++++++++--- scripts/pylib/twister/twisterlib/testplan.py | 9 ++++--- scripts/tests/twister_blackbox/test_error.py | 24 ++++++++++++++----- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/environment.py b/scripts/pylib/twister/twisterlib/environment.py index 03f6ab7f430..0d14345317a 100644 --- a/scripts/pylib/twister/twisterlib/environment.py +++ b/scripts/pylib/twister/twisterlib/environment.py @@ -203,7 +203,7 @@ Artificially long but functional example: and global timeout multiplier (this parameter)""") test_xor_subtest.add_argument( - "-s", "--test", action="append", + "-s", "--test", "--scenario", action="append", help="Run only the specified testsuite scenario. These are named by " "") @@ -747,8 +747,18 @@ def parse_arguments(parser, args, options = None): sys.exit(1) if not options.testsuite_root: - options.testsuite_root = [os.path.join(ZEPHYR_BASE, "tests"), - os.path.join(ZEPHYR_BASE, "samples")] + # if we specify a test scenario which is part of a suite directly, do + # not set testsuite root to default, just point to the test directory + # directly. + if options.test: + for scenario in options.test: + if dirname := os.path.dirname(scenario): + options.testsuite_root.append(dirname) + + # check again and make sure we have something set + if not options.testsuite_root: + options.testsuite_root = [os.path.join(ZEPHYR_BASE, "tests"), + os.path.join(ZEPHYR_BASE, "samples")] if options.show_footprint or options.compare_report: options.enable_size_report = True diff --git a/scripts/pylib/twister/twisterlib/testplan.py b/scripts/pylib/twister/twisterlib/testplan.py index f62aedab8cf..f55112349bd 100755 --- a/scripts/pylib/twister/twisterlib/testplan.py +++ b/scripts/pylib/twister/twisterlib/testplan.py @@ -506,7 +506,8 @@ class TestPlan: suite = TestSuite(root, suite_path, name, data=suite_dict, detailed_test_id=self.options.detailed_test_id) suite.add_subcases(suite_dict, subcases, ztest_suite_names) if testsuite_filter: - if suite.name and suite.name in testsuite_filter: + scenario = os.path.basename(suite.name) + if suite.name and (suite.name in testsuite_filter or scenario in testsuite_filter): self.testsuites[suite.name] = suite else: self.testsuites[suite.name] = suite @@ -739,8 +740,10 @@ class TestPlan: if exclude_tag and ts.tags.intersection(exclude_tag): instance.add_filter("Command line testsuite exclude filter", Filters.CMD_LINE) - if testsuite_filter and ts_name not in testsuite_filter: - instance.add_filter("TestSuite name filter", Filters.CMD_LINE) + if testsuite_filter: + normalized_f = [os.path.basename(_ts) for _ts in testsuite_filter] + if ts.id not in normalized_f: + instance.add_filter("Testsuite name filter", Filters.CMD_LINE) if arch_filter and plat.arch not in arch_filter: instance.add_filter("Command line testsuite arch filter", Filters.CMD_LINE) diff --git a/scripts/tests/twister_blackbox/test_error.py b/scripts/tests/twister_blackbox/test_error.py index 85cb726a313..e5b3d428ed5 100644 --- a/scripts/tests/twister_blackbox/test_error.py +++ b/scripts/tests/twister_blackbox/test_error.py @@ -20,12 +20,22 @@ from twisterlib.error import TwisterRuntimeError class TestError: TESTDATA_1 = [ ( + os.path.join(TEST_DATA, 'tests', 'dummy'), os.path.join('scripts', 'tests', 'twister_blackbox', 'test_data', 'tests', 'dummy', 'agnostic', 'group1', 'subgroup1', 'dummy.agnostic.group1.subgroup1'), SystemExit ), - ('dummy.agnostic.group1.subgroup1', TwisterRuntimeError), + ( + None, + 'dummy.agnostic.group1.subgroup1', + TwisterRuntimeError + ), + ( + os.path.join(TEST_DATA, 'tests', 'dummy'), + 'dummy.agnostic.group1.subgroup1', + SystemExit + ) ] @classmethod @@ -40,15 +50,17 @@ class TestError: pass @pytest.mark.parametrize( - 'test, expected_exception', + 'testroot, test, expected_exception', TESTDATA_1, - ids=['valid', 'invalid'] + ids=['valid', 'invalid', 'valid'] ) @mock.patch.object(TestPlan, 'TESTSUITE_FILENAME', testsuite_filename_mock) - def test_test(self, out_path, test, expected_exception): + def test_test(self, out_path, testroot, test, expected_exception): test_platforms = ['qemu_x86', 'frdm_k64f'] - path = os.path.join(TEST_DATA, 'tests', 'dummy') - args = ['-i', '--outdir', out_path, '-T', path, '--test', test, '-y'] + \ + args = [] + if testroot: + args = ['-T', testroot] + args += ['-i', '--outdir', out_path, '--test', test, '-y'] + \ [val for pair in zip( ['-p'] * len(test_platforms), test_platforms ) for val in pair]