| """
|
| Test runner for TouchGrass project.
|
|
|
| This script runs all unit tests and generates a comprehensive test report.
|
| """
|
|
|
| import subprocess
|
| import sys
|
| import argparse
|
| from pathlib import Path
|
| from datetime import datetime
|
| import json
|
|
|
|
|
| def run_tests(test_path: str = "tests", markers: str = None, verbose: bool = True,
|
| junit_xml: str = None, coverage: bool = False):
|
| """Run pytest with specified options."""
|
|
|
| cmd = ["pytest", test_path]
|
|
|
| if markers:
|
| cmd.extend(["-m", markers])
|
|
|
| if verbose:
|
| cmd.append("-v")
|
|
|
| if junit_xml:
|
| cmd.extend(["--junit-xml", junit_xml])
|
|
|
| if coverage:
|
| cmd.extend([
|
| "--cov=TouchGrass",
|
| "--cov-report=html",
|
| "--cov-report=term"
|
| ])
|
|
|
|
|
| cmd.append("--tb=short")
|
|
|
| print(f"Running: {' '.join(cmd)}\n")
|
|
|
| result = subprocess.run(cmd)
|
|
|
| return result.returncode
|
|
|
|
|
| def generate_test_report(output_dir: str = "test_reports"):
|
| """Generate a comprehensive test report."""
|
| output_dir = Path(output_dir)
|
| output_dir.mkdir(parents=True, exist_ok=True)
|
|
|
| report = {
|
| "timestamp": datetime.now().isoformat(),
|
| "summary": {},
|
| "details": []
|
| }
|
|
|
|
|
| json_output = output_dir / "test_results.json"
|
| cmd = [
|
| "pytest", "tests",
|
| "-v",
|
| "--tb=short",
|
| f"--junit-xml={output_dir / 'junit.xml'}",
|
| "--json-report",
|
| f"--json-report-file={json_output}"
|
| ]
|
|
|
| try:
|
| subprocess.run(cmd, check=False)
|
| except Exception as e:
|
| print(f"Warning: Could not generate JSON report: {e}")
|
|
|
|
|
| if json_output.exists():
|
| with open(json_output, 'r') as f:
|
| try:
|
| results = json.load(f)
|
| report["summary"] = {
|
| "total": results.get("summary", {}).get("total", 0),
|
| "passed": results.get("summary", {}).get("passed", 0),
|
| "failed": results.get("summary", {}).get("failed", 0),
|
| "skipped": results.get("summary", {}).get("skipped", 0)
|
| }
|
| except json.JSONDecodeError:
|
| pass
|
|
|
|
|
| report_file = output_dir / "test_report.json"
|
| with open(report_file, 'w') as f:
|
| json.dump(report, f, indent=2)
|
|
|
| print(f"\n✓ Test report generated at {report_file}")
|
|
|
| return report
|
|
|
|
|
| def main():
|
| parser = argparse.ArgumentParser(description="Run TouchGrass test suite")
|
| parser.add_argument("--tests", type=str, default="tests",
|
| help="Test directory or specific test file")
|
| parser.add_argument("--markers", type=str, default=None,
|
| help="Only run tests with specified markers (e.g., 'not slow')")
|
| parser.add_argument("--no-verbose", action="store_true",
|
| help="Disable verbose output")
|
| parser.add_argument("--junit-xml", type=str, default=None,
|
| help="Output JUnit XML report to specified file")
|
| parser.add_argument("--coverage", action="store_true",
|
| help="Run with coverage reporting")
|
| parser.add_argument("--report-dir", type=str, default="test_reports",
|
| help="Directory for test reports")
|
| parser.add_argument("--skip-report", action="store_true",
|
| help="Skip generating test report")
|
|
|
| args = parser.parse_args()
|
|
|
|
|
| exit_code = run_tests(
|
| test_path=args.tests,
|
| markers=args.markers,
|
| verbose=not args.no_verbose,
|
| junit_xml=args.junit_xml,
|
| coverage=args.coverage
|
| )
|
|
|
|
|
| if not args.skip_report:
|
| generate_test_report(args.report_dir)
|
|
|
| print("\n" + "=" * 60)
|
| if exit_code == 0:
|
| print("✓ All tests passed!")
|
| else:
|
| print(f"✗ Some tests failed (exit code: {exit_code})")
|
| print("=" * 60)
|
|
|
| return exit_code
|
|
|
|
|
| if __name__ == "__main__":
|
| exit_code = main()
|
| sys.exit(exit_code)
|
|
|