[PATCH v3 01/10] binman: support running multiple tests

Sam Day via B4 Relay devnull+me.samcday.com at kernel.org
Wed Jun 10 03:27:39 CEST 2026


From: Sam Day <me at samcday.com>

The helptext for `binman test` suggests that this was already supported,
but it wasn't properly wired up.
---
 tools/binman/main.py            |  8 ++++----
 tools/u_boot_pylib/test_util.py | 23 ++++++++++++++++-------
 2 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/tools/binman/main.py b/tools/binman/main.py
index a0c775fd629..5473789361d 100755
--- a/tools/binman/main.py
+++ b/tools/binman/main.py
@@ -58,8 +58,8 @@ def RunTests(debug, verbosity, processes, test_preserve_dirs, args, toolpath):
             the output directory for this test. Both directories are displayed
             on the command line.
         processes: Number of processes to use to run tests (None=same as #CPUs)
-        args: List of positional args provided to binman. This can hold a test
-            name to execute (as in 'binman test testSections', for example)
+        args: List of positional args provided to binman. This can hold test
+            names to execute (as in 'binman test testSections', for example)
         toolpath: List of paths to use for tools
     """
     from binman import bintool_test
@@ -72,13 +72,13 @@ def RunTests(debug, verbosity, processes, test_preserve_dirs, args, toolpath):
     from binman import image_test
     import doctest
 
-    test_name = args and args[0] or None
+    test_names = args or None
 
     # Run the entry tests first ,since these need to be the first to import the
     # 'entry' module.
     result = test_util.run_test_suites(
         'binman', debug, verbosity, False, test_preserve_dirs, processes,
-        test_name, toolpath,
+        test_names, toolpath,
         [bintool_test.TestBintool, entry_test.TestEntry, ftest.TestFunctional,
          fdt_test.TestFdt, elf_test.TestElf, image_test.TestImage,
          cbfs_util_test.TestCbfs, fip_util_test.TestFip])
diff --git a/tools/u_boot_pylib/test_util.py b/tools/u_boot_pylib/test_util.py
index 364596d7a0c..ff275a7b7c0 100644
--- a/tools/u_boot_pylib/test_util.py
+++ b/tools/u_boot_pylib/test_util.py
@@ -157,7 +157,7 @@ def run_test_suites(toolname, debug, verbosity, no_capture, test_preserve_dirs,
             the output directory for this test. Both directories are displayed
             on the command line.
         processes: Number of processes to use to run tests (None=same as #CPUs)
-        test_name: Name of test to run, or None for all
+        test_name: Name of test, or list of test names, to run; None for all
         toolpath: List of paths to use for tools
         class_and_module_list: List of test classes (type class) and module
            names (type str) to run
@@ -182,12 +182,19 @@ def run_test_suites(toolname, debug, verbosity, no_capture, test_preserve_dirs,
         resultclass=FullTextTestResult,
     )
 
-    if use_concurrent and processes != 1 and not test_name:
+    if isinstance(test_name, str):
+        test_names = [test_name]
+    else:
+        test_names = list(test_name or [])
+    test_name_set = set(test_names)
+
+    if use_concurrent and processes != 1 and not test_names:
         suite = ConcurrentTestSuite(suite,
                 fork_for_tests(processes or multiprocessing.cpu_count()))
 
     for module in class_and_module_list:
-        if isinstance(module, str) and (not test_name or test_name == module):
+        if (isinstance(module, str) and
+                (not test_names or module in test_name_set)):
             suite.addTests(doctest.DocTestSuite(module))
 
     for module in class_and_module_list:
@@ -197,15 +204,17 @@ def run_test_suites(toolname, debug, verbosity, no_capture, test_preserve_dirs,
         if hasattr(module, 'setup_test_args'):
             setup_test_args = getattr(module, 'setup_test_args')
             setup_test_args(preserve_indir=test_preserve_dirs,
-                preserve_outdirs=test_preserve_dirs and test_name is not None,
+                preserve_outdirs=test_preserve_dirs and bool(test_names),
                 toolpath=toolpath, verbosity=verbosity, no_capture=no_capture)
-        if test_name:
+        if test_names:
             # Since Python v3.5 If an ImportError or AttributeError occurs
             # while traversing a name then a synthetic test that raises that
             # error when run will be returned. Check that the requested test
             # exists, otherwise these errors are included in the results.
-            if test_name in loader.getTestCaseNames(module):
-                suite.addTests(loader.loadTestsFromName(test_name, module))
+            module_test_names = loader.getTestCaseNames(module)
+            for name in test_names:
+                if name in module_test_names:
+                    suite.addTests(loader.loadTestsFromName(name, module))
         else:
             suite.addTests(loader.loadTestsFromTestCase(module))
 

-- 
2.54.0




More information about the U-Boot mailing list