"""Run every test module in one go.
Each test module is independently runnable and also pytest-compatible; this
runner exists so the suite can be executed without pytest installed.
"""
from __future__ import annotations
import importlib.util
import sys
import traceback
from pathlib import Path
HERE = Path(__file__).resolve().parent
def load(path: Path):
spec = importlib.util.spec_from_file_location(path.stem, path)
module = importlib.util.module_from_spec(spec)
sys.modules[path.stem] = module
assert spec.loader is not None
spec.loader.exec_module(module)
return module
def main() -> int:
total = failed = 0
verbose = "-v" in sys.argv
modules = sorted(p for p in HERE.glob("test_*.py"))
for path in modules:
try:
module = load(path)
except Exception: # noqa: BLE001
print(f"\n{path.stem}: FAILED TO IMPORT")
traceback.print_exc()
failed += 1
continue
tests = [
(n, f) for n, f in sorted(vars(module).items()) if n.startswith("test_") and callable(f)
]
module_failed = 0
for name, fn in tests:
total += 1
try:
fn()
except Exception as exc: # noqa: BLE001
module_failed += 1
print(f"FAIL {path.stem}::{name}")
print(f" {type(exc).__name__}: {exc}")
if verbose:
traceback.print_exc()
else:
if verbose:
print(f"ok {path.stem}::{name}")
failed += module_failed
status = "ok" if not module_failed else f"{module_failed} FAILED"
print(f"{status:>10} {path.stem} ({len(tests)} tests)")
print(f"\n{total - failed}/{total} passed across {len(modules)} modules")
return 1 if failed else 0
if __name__ == "__main__":
raise SystemExit(main())