NutriLoop / scripts /test_api.py
AB1N05's picture
Nutriloop V2 Backend - Global Model Architected
1fa55f4
Raw
History Blame Contribute Delete
4.04 kB
"""
End-to-end test script for NutriLoop AI API.
Tests /health, /predict, /cold-start, and news adjuster.
"""
import httpx
import sys
from pathlib import Path
# Add project root to path
project_root = Path(__file__).resolve().parent.parent
if str(project_root) not in sys.path:
sys.path.insert(0, str(project_root))
BASE_URL = "http://localhost:7860"
def test_health():
"""Test GET /health endpoint."""
print("\n[TEST] GET /health")
response = httpx.get(f"{BASE_URL}/health", timeout=10.0)
data = response.json()
print(f" Status: {response.status_code}")
print(f" Response: {data}")
assert response.status_code == 200, f"Expected 200, got {response.status_code}"
assert data["status"] == "ok", f"Expected status='ok', got {data['status']}"
print(" PASS")
def test_predict_global():
"""Test POST /predict with known restaurant_id and item."""
print("\n[TEST] POST /predict")
# Use a restaurant that might have a model, or test cold-start fallback
response = httpx.post(
f"{BASE_URL}/predict",
json={
"restaurant_id": "test_restaurant_001",
"item_name": "biriyani",
"city": "Kochi",
"days": 7,
},
timeout=10.0,
)
data = response.json()
print(f" Status: {response.status_code}")
print(f" Response: {data}")
assert response.status_code == 200, f"Expected 200, got {response.status_code}"
assert "predictions" in data, "Missing 'predictions' in response"
assert len(data["predictions"]) == 7, f"Expected 7 predictions, got {len(data['predictions'])}"
assert data["source"] in ["global_model", "cold_start"], f"Invalid source: {data['source']}"
print(" PASS")
def test_cold_start():
"""Test POST /cold-start endpoint with Kochi coordinates."""
print("\n[TEST] POST /cold-start")
response = httpx.post(
f"{BASE_URL}/cold-start",
json={
"latitude": 9.9312,
"longitude": 76.2673,
"cuisine_type": "indian",
"avg_daily_quantity": 25.0,
"item_name": "puttu",
"days": 7,
},
timeout=10.0,
)
data = response.json()
print(f" Status: {response.status_code}")
print(f" Response: {data}")
assert response.status_code == 200, f"Expected 200, got {response.status_code}"
assert data["source"] == "cold_start", f"Expected source='cold_start', got {data['source']}"
assert len(data["predictions"]) == 7, f"Expected 7 predictions, got {len(data['predictions'])}"
assert data["news_multiplier"] > 0, "Invalid news_multiplier"
print(" PASS")
def test_news_adjuster():
"""Test news adjuster directly."""
print("\n[TEST] News adjuster (Kochi)")
from app.news_adjuster import get_news_multiplier
multiplier = get_news_multiplier("Kochi")
print(f" Multiplier: {multiplier}")
assert 0.5 <= multiplier <= 2.0, f"Multiplier out of range: {multiplier}"
print(" PASS")
def main():
"""Run all tests."""
print("=" * 50)
print("NutriLoop AI - End-to-End API Tests")
print("=" * 50)
# Check if server is running
try:
httpx.get(f"{BASE_URL}/health", timeout=5.0)
except httpx.ConnectError:
print(f"\nERROR: Cannot connect to {BASE_URL}")
print("Make sure the server is running:")
print(" uv run uvicorn app.main:app --reload --port 7860")
sys.exit(1)
passed = 0
failed = 0
tests = [
("Health", test_health),
("Predict", test_predict_global),
("Cold-Start", test_cold_start),
("News Adjuster", test_news_adjuster),
]
for name, test_fn in tests:
try:
test_fn()
passed += 1
except Exception as e:
print(f" FAIL: {e}")
failed += 1
print("\n" + "=" * 50)
print(f"Results: {passed} passed, {failed} failed")
print("=" * 50)
if failed > 0:
sys.exit(1)
if __name__ == "__main__":
main()