"""Load unittest files without letting an empty selection report success.""" import argparse from concurrent.futures import ThreadPoolExecutor import importlib.util import subprocess from pathlib import Path import sys import unittest def suite_for(path, test_name=None): path = Path(path).resolve() sys.path.insert(0, str(path.parent)) spec = importlib.util.spec_from_file_location(path.stem, path) assert spec is not None and spec.loader is not None module = importlib.util.module_from_spec(spec) sys.modules[path.stem] = module spec.loader.exec_module(module) loader = unittest.TestLoader() suite = ( loader.loadTestsFromName(test_name, module) if test_name else loader.loadTestsFromModule(module) ) if suite.countTestCases() == 0: raise ValueError(f"no tests collected from {path}") return suite def run_file(path): result = subprocess.run( [sys.executable, __file__, path], capture_output=True, text=True ) print(f"{'ok' if result.returncode == 0 else 'FAILED'} {path}", file=sys.stderr) if result.returncode: print(result.stdout + result.stderr, file=sys.stderr) return result.returncode == 0 def main(): parser = argparse.ArgumentParser() parser.add_argument("--jobs", type=int, default=1) parser.add_argument("paths", nargs="+") args = parser.parse_args() if len(args.paths) > 1: with ThreadPoolExecutor(max_workers=max(1, args.jobs)) as pool: outcomes = list(pool.map(run_file, args.paths)) return 0 if all(outcomes) else 1 try: suite = suite_for(args.paths[0]) except ValueError as error: print(error, file=sys.stderr) return 1 return 0 if unittest.TextTestRunner(verbosity=2).run(suite).wasSuccessful() else 1 if __name__ == "__main__": sys.exit(main())