Spaces:
Sleeping
Sleeping
| import os | |
| import sys | |
| from fastapi.testclient import TestClient | |
| # Ensure project root is in path | |
| project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) | |
| if project_root not in sys.path: | |
| sys.path.append(project_root) | |
| from src.api import app | |
| def test_health_check() -> None: | |
| """Verifies that the /health API endpoint responds with success status.""" | |
| with TestClient(app) as client: | |
| response = client.get("/health") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["status"] == "healthy" | |
| assert "model_loaded" in data | |
| def test_predict_endpoint() -> None: | |
| """Verifies that a valid customer prediction payload yields correct structure and values.""" | |
| payload = { | |
| "recency": 10, | |
| "frequency": 5, | |
| "monetary": 250.0, | |
| "basket_size": 8.0, | |
| "avg_days_between": 20.0, | |
| "recent_orders_ratio": 0.8, | |
| "is_uk": 1 | |
| } | |
| with TestClient(app) as client: | |
| response = client.post("/predict", json=payload) | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert "churn_probability" in data | |
| assert "risk_tier" in data | |
| assert "recommendation" in data | |
| assert isinstance(data["churn_probability"], float) | |
| def test_predict_batch_endpoint() -> None: | |
| """Verifies that a valid list of customer profiles returns batched prediction arrays.""" | |
| payload = { | |
| "customers": [ | |
| { | |
| "recency": 10, | |
| "frequency": 5, | |
| "monetary": 250.0, | |
| "basket_size": 8.0 | |
| }, | |
| { | |
| "recency": 200, | |
| "frequency": 1, | |
| "monetary": 50.0, | |
| "basket_size": 2.0 | |
| } | |
| ] | |
| } | |
| with TestClient(app) as client: | |
| response = client.post("/predict_batch", json=payload) | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert "predictions" in data | |
| assert len(data["predictions"]) == 2 | |
| for pred in data["predictions"]: | |
| assert "churn_probability" in pred | |
| assert "risk_tier" in pred | |
| assert "recommendation" in pred | |
| def test_monitor_drift_endpoint() -> None: | |
| """Verifies that the /monitor endpoint returns the statistical drift analysis report.""" | |
| with TestClient(app) as client: | |
| response = client.get("/monitor") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert "drift_detected" in data | |
| assert "drift_status" in data | |
| assert "message" in data | |
| def test_shadow_stats_endpoint() -> None: | |
| """Verifies that the /shadow_stats endpoint returns Champion vs Challenger metrics.""" | |
| with TestClient(app) as client: | |
| response = client.get("/shadow_stats") | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert "total_predictions" in data | |
| assert "champion_mean" in data | |
| assert "challenger_mean" in data | |
| assert "mean_absolute_deviation" in data | |
| assert "agreement_rate" in data | |
| assert "recent_logs" in data | |