#!/usr/bin/env python3 import argparse import os import sys import subprocess from typing import List def build_pytest_cmd(args: argparse.Namespace) -> List[str]: cmd = [sys.executable, "-m", "pytest"] # Пакеты тестов по умолчанию test_paths = [ "uploader-bot/tests", ] cmd += test_paths # Маркеры if args.mark: cmd += ["-m", args.mark] # Параллельность (pytest-xdist) if args.parallel: cmd += ["-n", str(args.parallel)] # Verbose if args.verbose: cmd += ["-vv"] # Coverage if args.coverage: # Требуется pytest-cov cov_targets = args.cov_targets or ["app"] cmd += ["--cov", *cov_targets, "--cov-report", "term-missing"] if args.cov_xml: cmd += ["--cov-report", "xml:coverage.xml"] if args.cov_html: cmd += ["--cov-report", "html:coverage_html"] # Запрет пропуска warning как ошибок if args.strict: cmd += ["-W", "error"] return cmd def main() -> int: parser = argparse.ArgumentParser(description="Unified test runner for uploader-bot") parser.add_argument("--mark", help="pytest -m expression (e.g. 'performance or e2e')", default=None) parser.add_argument("--parallel", "-n", type=int, help="Number of workers for pytest-xdist", default=None) parser.add_argument("--verbose", "-v", action="store_true", help="Verbose output") parser.add_argument("--coverage", action="store_true", help="Enable coverage via pytest-cov") parser.add_argument("--cov-targets", nargs="*", help="Modules for coverage (default: app)", default=None) parser.add_argument("--cov-xml", action="store_true", help="Emit coverage.xml") parser.add_argument("--cov-html", action="store_true", help="Emit HTML coverage report to coverage_html/") parser.add_argument("--strict", action="store_true", help="Treat warnings as errors") parser.add_argument("--maxfail", type=int, default=1, help="Stop after N failures") parser.add_argument("--no-capture", action="store_true", help="Disable output capture (-s)") args = parser.parse_args() cmd = build_pytest_cmd(args) # Дополнительные флаги cmd += ["--maxfail", str(args.maxfail)] if args.no_capture: cmd += ["-s"] print("[run_tests] Command:", " ".join(cmd), flush=True) env = os.environ.copy() try: return subprocess.call(cmd, env=env) except KeyboardInterrupt: return 130 if __name__ == "__main__": raise SystemExit(main())