| | """
|
| | 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)
|
| |
|