Currently, kunit.py allows listing all individual tests via --list_tests.
However, users often need to see only the available test suites.

Add --list_suites to show suites. This option parses the test list output
from the kernel and prints only the suite names.

Example of the output of --list_suites:
  example_init
  miscdev_init
  printk-ringbuffer

Signed-off-by: Ryota Sakamoto <[email protected]>
---
 tools/testing/kunit/kunit.py           | 16 ++++++++++++++--
 tools/testing/kunit/kunit_tool_test.py | 16 +++++++++++++---
 2 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py
index 
4ec5ecba6d49b1ba3360515a2b66a2a98813bd18..742f5c555666021f61c44a98229bb34f9664d3c2
 100755
--- a/tools/testing/kunit/kunit.py
+++ b/tools/testing/kunit/kunit.py
@@ -63,6 +63,7 @@ class KunitExecRequest(KunitParseRequest):
        run_isolated: Optional[str]
        list_tests: bool
        list_tests_attr: bool
+       list_suites: bool
 
 @dataclass
 class KunitRequest(KunitExecRequest, KunitBuildRequest):
@@ -168,6 +169,12 @@ def exec_tests(linux: kunit_kernel.LinuxSourceTree, 
request: KunitExecRequest) -
                for line in attr_output:
                        print(line.rstrip())
                return KunitResult(status=KunitStatus.SUCCESS, elapsed_time=0.0)
+       if request.list_suites:
+               tests = _list_tests(linux, request)
+               output = _suites_from_test_list(tests)
+               for line in output:
+                       print(line.rstrip())
+               return KunitResult(status=KunitStatus.SUCCESS, elapsed_time=0.0)
        if request.run_isolated:
                tests = _list_tests(linux, request)
                if request.run_isolated == 'test':
@@ -438,6 +445,9 @@ def add_exec_opts(parser: argparse.ArgumentParser) -> None:
        parser.add_argument('--list_tests_attr', help='If set, list all tests 
and test '
                            'attributes.',
                            action='store_true')
+       parser.add_argument('--list_suites', help='If set, list all suites that 
will be '
+                           'run.',
+                           action='store_true')
 
 def add_parse_opts(parser: argparse.ArgumentParser) -> None:
        parser.add_argument('--raw_output', help='If set don\'t parse output 
from kernel. '
@@ -501,7 +511,8 @@ def run_handler(cli_args: argparse.Namespace) -> None:
                                        kernel_args=cli_args.kernel_args,
                                        run_isolated=cli_args.run_isolated,
                                        list_tests=cli_args.list_tests,
-                                       
list_tests_attr=cli_args.list_tests_attr)
+                                       
list_tests_attr=cli_args.list_tests_attr,
+                                       list_suites=cli_args.list_suites)
        result = run_tests(linux, request)
        if result.status != KunitStatus.SUCCESS:
                sys.exit(1)
@@ -550,7 +561,8 @@ def exec_handler(cli_args: argparse.Namespace) -> None:
                                        kernel_args=cli_args.kernel_args,
                                        run_isolated=cli_args.run_isolated,
                                        list_tests=cli_args.list_tests,
-                                       
list_tests_attr=cli_args.list_tests_attr)
+                                       
list_tests_attr=cli_args.list_tests_attr,
+                                       list_suites=cli_args.list_suites)
        result = exec_tests(linux, exec_request)
        stdout.print_with_timestamp((
                'Elapsed time: %.3fs\n') % (result.elapsed_time))
diff --git a/tools/testing/kunit/kunit_tool_test.py 
b/tools/testing/kunit/kunit_tool_test.py
index 
b67408147c1faaab12b168aabe3bfba8bf1b00aa..a7402afd33743455b3ece72a495a6c8769ed51af
 100755
--- a/tools/testing/kunit/kunit_tool_test.py
+++ b/tools/testing/kunit/kunit_tool_test.py
@@ -855,7 +855,7 @@ class KUnitMainTest(unittest.TestCase):
                self.linux_source_mock.run_kernel.return_value = ['TAP version 
14', 'init: random output'] + want
 
                got = kunit._list_tests(self.linux_source_mock,
-                                    kunit.KunitExecRequest(None, None, False, 
False, '.kunit', 300, 'suite*', '', None, None, 'suite', False, False))
+                                    kunit.KunitExecRequest(None, None, False, 
False, '.kunit', 300, 'suite*', '', None, None, 'suite', False, False, False))
                self.assertEqual(got, want)
                # Should respect the user's filter glob when listing tests.
                self.linux_source_mock.run_kernel.assert_called_once_with(
@@ -868,7 +868,7 @@ class KUnitMainTest(unittest.TestCase):
 
                # Should respect the user's filter glob when listing tests.
                mock_tests.assert_called_once_with(mock.ANY,
-                                    kunit.KunitExecRequest(None, None, False, 
False, '.kunit', 300, 'suite*.test*', '', None, None, 'suite', False, False))
+                                    kunit.KunitExecRequest(None, None, False, 
False, '.kunit', 300, 'suite*.test*', '', None, None, 'suite', False, False, 
False))
                self.linux_source_mock.run_kernel.assert_has_calls([
                        mock.call(args=None, build_dir='.kunit', 
filter_glob='suite.test*', filter='', filter_action=None, timeout=300),
                        mock.call(args=None, build_dir='.kunit', 
filter_glob='suite2.test*', filter='', filter_action=None, timeout=300),
@@ -881,13 +881,23 @@ class KUnitMainTest(unittest.TestCase):
 
                # Should respect the user's filter glob when listing tests.
                mock_tests.assert_called_once_with(mock.ANY,
-                                    kunit.KunitExecRequest(None, None, False, 
False, '.kunit', 300, 'suite*', '', None, None, 'test', False, False))
+                                    kunit.KunitExecRequest(None, None, False, 
False, '.kunit', 300, 'suite*', '', None, None, 'test', False, False, False))
                self.linux_source_mock.run_kernel.assert_has_calls([
                        mock.call(args=None, build_dir='.kunit', 
filter_glob='suite.test1', filter='', filter_action=None, timeout=300),
                        mock.call(args=None, build_dir='.kunit', 
filter_glob='suite.test2', filter='', filter_action=None, timeout=300),
                        mock.call(args=None, build_dir='.kunit', 
filter_glob='suite2.test1', filter='', filter_action=None, timeout=300),
                ])
 
+       @mock.patch.object(kunit, '_list_tests')
+       @mock.patch.object(sys, 'stdout', new_callable=io.StringIO)
+       def test_list_suites(self, mock_stdout, mock_tests):
+               mock_tests.return_value = ['suite.test1', 'suite.test2', 
'suite2.test1']
+               kunit.main(['run', '--list_suites'])
+
+               want = ['suite', 'suite2']
+               output = mock_stdout.getvalue().split()
+               self.assertEqual(output, want)
+
        @mock.patch.object(sys, 'stdout', new_callable=io.StringIO)
        def test_list_cmds(self, mock_stdout):
                kunit.main(['--list-cmds'])

---
base-commit: db0c35ca36526f3072affcb573631ccf8c85f827
change-id: 20260211-kunit-list_suites-ca0c5cb7ed6d

Best regards,
-- 
Ryota Sakamoto <[email protected]>


Reply via email to