ai-talent-finder-backend / run_all_tests.py
ilyass yani
Deploiement backend dans HF Spaces
9df97a2
Raw
History Blame
10.9 kB
#!/usr/bin/env python3
"""
Run All Tests β€” Comprehensive Test Suite
Exécute tous les tests (représentatif + chatbot + E2E) et génère un rapport final.
"""
import subprocess
import sys
import json
import os
from pathlib import Path
from datetime import datetime
class TestRunner:
"""Coordonne l'exΓ©cution de tous les tests."""
def __init__(self):
self.results = []
self.backend_dir = Path(__file__).parent
self.reports_dir = self.backend_dir / "reports"
self.reports_dir.mkdir(exist_ok=True)
def run_command(self, cmd: list, description: str) -> bool:
"""Exécute une commande et retourne succès/échec."""
print(f"\n{'='*70}")
print(f"πŸš€ {description}")
print(f"{'='*70}")
print(f"Command: {' '.join(cmd)}")
print()
try:
result = subprocess.run(cmd, cwd=self.backend_dir, timeout=300)
success = result.returncode == 0
if success:
print(f"\nβœ… {description} β€” PASSED")
else:
print(f"\n❌ {description} β€” FAILED (exit code: {result.returncode})")
self.results.append({
"test": description,
"passed": success,
"timestamp": datetime.now().isoformat()
})
return success
except subprocess.TimeoutExpired:
print(f"\n❌ {description} β€” TIMEOUT (>5min)")
self.results.append({
"test": description,
"passed": False,
"error": "Timeout",
"timestamp": datetime.now().isoformat()
})
return False
except Exception as e:
print(f"\n❌ {description} β€” ERROR: {e}")
self.results.append({
"test": description,
"passed": False,
"error": str(e),
"timestamp": datetime.now().isoformat()
})
return False
def run_all_tests(self):
"""ExΓ©cute tous les tests."""
print("\n" + "#"*70)
print("# AI TALENT FINDER β€” COMPREHENSIVE TEST SUITE")
print("#"*70)
print(f"Backend directory: {self.backend_dir}")
print(f"Reports directory: {self.reports_dir}")
print(f"Start time: {datetime.now().isoformat()}")
# Test 1: Representative Tests
test1_passed = self.run_command(
[sys.executable, "run_representative_tests.py"],
"Test 1: Representative Tests (CV, Skills, Matching, Edge Cases)"
)
# Test 2: Chatbot Tests (optional, requires API key)
if os.getenv("ANTHROPIC_API_KEY"):
test2_passed = self.run_command(
[sys.executable, "test_chatbot_recruiter_scenarios.py"],
"Test 2: Chatbot Quality Tests"
)
else:
print("\n⚠️ Test 2: Chatbot Quality Tests β€” SKIPPED (ANTHROPIC_API_KEY not set)")
self.results.append({
"test": "Test 2: Chatbot Quality Tests",
"passed": None,
"skipped": True,
"reason": "ANTHROPIC_API_KEY not set",
"timestamp": datetime.now().isoformat()
})
test2_passed = True
# Test 3: E2E Tests (optional, requires frontend running)
frontend_url = os.getenv("FRONTEND_URL")
if frontend_url:
test3_passed = self.run_command(
[sys.executable, "test_e2e_recruiter_flow.py"],
"Test 3: E2E Recruiter Flow Tests"
)
else:
print("\n⚠️ Test 3: E2E Recruiter Flow Tests β€” SKIPPED (FRONTEND_URL not set)")
self.results.append({
"test": "Test 3: E2E Recruiter Flow Tests",
"passed": None,
"skipped": True,
"reason": "FRONTEND_URL not set",
"timestamp": datetime.now().isoformat()
})
test3_passed = True
# Print overall summary
self.print_summary()
# Save comprehensive report
self.save_report()
# Return success if all required tests passed
all_passed = all(r.get("passed", True) for r in self.results if not r.get("skipped"))
return all_passed
def print_summary(self):
"""Affiche un rΓ©sumΓ© des rΓ©sultats."""
print("\n" + "="*70)
print("TEST EXECUTION SUMMARY")
print("="*70)
total = len(self.results)
passed = sum(1 for r in self.results if r.get("passed", False))
failed = sum(1 for r in self.results if r.get("passed", False) == False)
skipped = sum(1 for r in self.results if r.get("skipped", False))
print(f"\nπŸ“Š Results:")
print(f" βœ… Passed: {passed}/{total}")
print(f" ❌ Failed: {failed}/{total}")
print(f" ⏭️ Skipped: {skipped}/{total}")
print(f"\nπŸ“‹ Details:")
for result in self.results:
test_name = result.get("test", "unknown")
if result.get("skipped"):
reason = result.get("reason", "unknown")
print(f" ⏭️ {test_name}")
print(f" Reason: {reason}")
elif result.get("passed"):
print(f" βœ… {test_name}")
else:
error = result.get("error", "unknown")
print(f" ❌ {test_name}")
if error:
print(f" Error: {error}")
print()
def save_report(self):
"""Sauvegarde un rapport JSON complet."""
report_path = self.reports_dir / "test_suite_final_report.json"
final_report = {
"title": "AI Talent Finder β€” Comprehensive Test Suite",
"execution_date": datetime.now().isoformat(),
"backend_path": str(self.backend_dir),
"backend_env": {
"PYTHONPATH": os.getenv("PYTHONPATH", ""),
"VIRTUAL_ENV": os.getenv("VIRTUAL_ENV", ""),
"CONDA_DEFAULT_ENV": os.getenv("CONDA_DEFAULT_ENV", ""),
},
"test_results": self.results,
"summary": {
"total_tests": len(self.results),
"passed": sum(1 for r in self.results if r.get("passed", False)),
"failed": sum(1 for r in self.results if r.get("passed", False) == False),
"skipped": sum(1 for r in self.results if r.get("skipped", False)),
}
}
with open(report_path, "w") as f:
json.dump(final_report, f, indent=2)
print(f"\nπŸ“„ Full report saved to: {report_path}")
# Also save to a txt version for readability
txt_path = self.reports_dir / "test_suite_final_report.txt"
with open(txt_path, "w") as f:
f.write("="*70 + "\n")
f.write("AI TALENT FINDER β€” COMPREHENSIVE TEST SUITE\n")
f.write("="*70 + "\n\n")
f.write(f"Execution Date: {datetime.now().isoformat()}\n")
f.write(f"Backend Path: {self.backend_dir}\n\n")
f.write("RESULTS\n")
f.write("-"*70 + "\n")
for result in self.results:
test_name = result.get("test", "unknown")
timestamp = result.get("timestamp", "")
if result.get("skipped"):
reason = result.get("reason", "unknown")
f.write(f"⏭️ {test_name}\n")
f.write(f" Status: SKIPPED\n")
f.write(f" Reason: {reason}\n")
elif result.get("passed"):
f.write(f"βœ… {test_name}\n")
f.write(f" Status: PASSED\n")
else:
error = result.get("error", "unknown")
f.write(f"❌ {test_name}\n")
f.write(f" Status: FAILED\n")
if error:
f.write(f" Error: {error}\n")
if timestamp:
f.write(f" Timestamp: {timestamp}\n")
f.write("\n")
f.write("="*70 + "\n")
f.write("SUMMARY\n")
f.write("-"*70 + "\n")
f.write(f"Total Tests: {len(self.results)}\n")
f.write(f"Passed: {sum(1 for r in self.results if r.get('passed', False))}\n")
f.write(f"Failed: {sum(1 for r in self.results if r.get('passed', False) == False)}\n")
f.write(f"Skipped: {sum(1 for r in self.results if r.get('skipped', False))}\n")
print(f"πŸ“„ Text report saved to: {txt_path}")
def main():
"""Main entry point."""
print("""
╔══════════════════════════════════════════════════════════════════════╗
β•‘ β•‘
β•‘ AI TALENT FINDER β€” COMPREHENSIVE TEST SUITE β•‘
β•‘ β•‘
β•‘ Tests: Representative | Chatbot | E2E β•‘
β•‘ Reports: JSON + Text + Per-test artifacts β•‘
β•‘ β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
""")
print("CONFIGURATION")
print("-"*70)
print(f"Python Version: {sys.version.split()[0]}")
print(f"Executable: {sys.executable}")
api_key_set = bool(os.getenv("ANTHROPIC_API_KEY"))
frontend_url = os.getenv("FRONTEND_URL")
print(f"ANTHROPIC_API_KEY: {'βœ… SET' if api_key_set else '❌ NOT SET'} (chatbot tests: {'enabled' if api_key_set else 'skipped'})")
print(f"FRONTEND_URL: {'βœ… SET' if frontend_url else '❌ NOT SET'} (E2E tests: {'enabled' if frontend_url else 'skipped'})")
print()
runner = TestRunner()
success = runner.run_all_tests()
print("\n" + "#"*70)
if success:
print("# βœ… ALL TESTS PASSED β€” SYSTEM READY FOR PRODUCTION")
else:
print("# ❌ SOME TESTS FAILED β€” SEE REPORTS FOR DETAILS")
print("#"*70)
return 0 if success else 1
if __name__ == "__main__":
sys.exit(main())