import argparse import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "tests")) from categorizer import categorize_all from batcher import plan def _print_plan(records, options) -> int: batches = plan(records, include_opt_in=options.include_opt_in, xdist=not options.no_xdist) for b in batches: status = "SKIP" if b.skip_reason else "RUN" print(f"[{status}] {b.label}: {len(b.files)} files, est {b.estimated_seconds:.1f}s, args={b.pytest_args}") if b.skip_reason: print(f" reason: {b.skip_reason}") return 0 def _print_audit(records, strict: bool) -> int: auto = [r for r in records if r.source == "auto"] print(f"Auto-inferred (unclassified) records: {len(auto)}") for r in auto: print(f" {r.filename}: fc={r.fixture_class.value}, subs={r.subsystems}, bg={r.batch_group}") if strict: bad = [r for r in auto if len(r.subsystems) > 1] if bad: print(f"STRICT: {len(bad)} auto-inferred files have multiple subsystems (probably cross-cutting):") for r in bad: print(f" {r.filename}: subs={r.subsystems}") return 1 return 0 def main() -> int: p = argparse.ArgumentParser() p.add_argument("--tests-dir", default="tests") p.add_argument("--registry", default="tests/test_categories.toml") p.add_argument("--tiers", default="1,2,3,H") p.add_argument("--include-opt-in", action="store_true") p.add_argument("--no-xdist", action="store_true") p.add_argument("--plan", action="store_true") p.add_argument("--audit", action="store_true") p.add_argument("--strict", action="store_true") options = p.parse_args() records = categorize_all(Path(options.tests_dir), Path(options.registry)) if options.audit: return _print_audit(records, strict=options.strict) if options.plan: return _print_plan(records, options) print("Phase 1 stub: no actual test execution yet. Use --plan or --audit.") return 0 if __name__ == "__main__": sys.exit(main())