Spaces:
Sleeping
Sleeping
| """ | |
| Testing Checkpoint 1 - Automated Validation Script | |
| Validates all requirements from IMPLEMENTATION_PROMPTS.md Checkpoint 1. | |
| """ | |
| import sys | |
| import time | |
| import json | |
| from pathlib import Path | |
| sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) | |
| import httpx | |
| BASE = "http://127.0.0.1:8000" | |
| results = [] | |
| def test(name, method, url, expect_status=200): | |
| start = time.perf_counter() | |
| try: | |
| r = getattr(httpx, method)(url, timeout=10) | |
| elapsed = (time.perf_counter() - start) * 1000 | |
| passed = r.status_code == expect_status | |
| if r.headers.get("content-type", "").startswith("application/json"): | |
| body = r.json() | |
| else: | |
| body = r.text[:300] | |
| results.append((name, passed, r.status_code, elapsed, body)) | |
| except Exception as e: | |
| results.append((name, False, 0, 0, str(e))) | |
| def main(): | |
| print() | |
| print("=" * 80) | |
| print(" TESTING CHECKPOINT 1 - Farm Help API") | |
| print("=" * 80) | |
| print() | |
| # --------------------------------------------------------------- | |
| # T1: Server health | |
| # --------------------------------------------------------------- | |
| test("GET / (root)", "get", f"{BASE}/") | |
| test("GET /health", "get", f"{BASE}/health") | |
| # --------------------------------------------------------------- | |
| # T4: Treatment with valid English name | |
| # --------------------------------------------------------------- | |
| test( | |
| "POST /treatment (English: Paddy Blast)", | |
| "post", | |
| f"{BASE}/api/disease/treatment?disease_name=Paddy%20Blast", | |
| ) | |
| # --------------------------------------------------------------- | |
| # T5: Treatment with Hindi name | |
| # --------------------------------------------------------------- | |
| hindi_encoded = "%E0%A4%A7%E0%A4%BE%E0%A4%A8%20%E0%A4%95%E0%A4%BE%20%E0%A4%AC%E0%A5%8D%E0%A4%B2%E0%A4%BE%E0%A4%B8%E0%A5%8D%E0%A4%9F" | |
| test( | |
| "POST /treatment (Hindi name)", | |
| "post", | |
| f"{BASE}/api/disease/treatment?disease_name={hindi_encoded}", | |
| ) | |
| # --------------------------------------------------------------- | |
| # T6: List all diseases | |
| # --------------------------------------------------------------- | |
| test("GET /list (all diseases)", "get", f"{BASE}/api/disease/list") | |
| # --------------------------------------------------------------- | |
| # T7: Filter by crop_type=Paddy | |
| # --------------------------------------------------------------- | |
| test( | |
| "GET /list?crop_type=Paddy", | |
| "get", | |
| f"{BASE}/api/disease/list?crop_type=Paddy", | |
| ) | |
| # --------------------------------------------------------------- | |
| # T8: FastAPI docs page | |
| # --------------------------------------------------------------- | |
| test("GET /docs (Swagger UI)", "get", f"{BASE}/docs") | |
| # --------------------------------------------------------------- | |
| # T9: Error handling - disease not found | |
| # --------------------------------------------------------------- | |
| test( | |
| "POST /treatment (404 - invalid name)", | |
| "post", | |
| f"{BASE}/api/disease/treatment?disease_name=CompletelyFakeDisease123", | |
| expect_status=404, | |
| ) | |
| # --------------------------------------------------------------- | |
| # Additional endpoint tests | |
| # --------------------------------------------------------------- | |
| test("GET /disease/1 (by ID)", "get", f"{BASE}/api/disease/1") | |
| test( | |
| "GET /disease/99999 (404)", | |
| "get", | |
| f"{BASE}/api/disease/99999", | |
| expect_status=404, | |
| ) | |
| test( | |
| "POST /detect (Paddy)", | |
| "post", | |
| f"{BASE}/api/disease/detect?crop_type=Paddy", | |
| ) | |
| # --------------------------------------------------------------- | |
| # Print results | |
| # --------------------------------------------------------------- | |
| print("-" * 80) | |
| print(" TEST RESULTS") | |
| print("-" * 80) | |
| all_pass = True | |
| for name, passed, status_code, elapsed_ms, body in results: | |
| icon = "PASS" if passed else "FAIL" | |
| time_flag = "OK" if elapsed_ms < 200 else "SLOW" | |
| if not passed: | |
| all_pass = False | |
| print( | |
| f" [{icon}] {name:45s} | HTTP {status_code:3d} | {elapsed_ms:7.1f}ms ({time_flag})" | |
| ) | |
| if not passed: | |
| detail = body if isinstance(body, str) else json.dumps(body)[:200] | |
| print(f" DETAIL: {detail}") | |
| # --------------------------------------------------------------- | |
| # Data validation | |
| # --------------------------------------------------------------- | |
| print() | |
| print("-" * 80) | |
| print(" DATA VALIDATION") | |
| print("-" * 80) | |
| for name, passed, status_code, elapsed_ms, body in results: | |
| if name == "GET /list (all diseases)" and passed and isinstance(body, dict): | |
| total = body.get("total", 0) | |
| ok = total >= 30 | |
| icon = "PASS" if ok else "FAIL" | |
| if not ok: | |
| all_pass = False | |
| print(f" [{icon}] Total diseases: {total} (expected >= 30)") | |
| if name == "GET /list?crop_type=Paddy" and passed and isinstance(body, dict): | |
| total = body.get("total", 0) | |
| diseases = body.get("diseases", []) | |
| crops = set(d.get("crop_type", "").lower() for d in diseases) | |
| filter_ok = crops == {"paddy"} or total == 0 | |
| icon = "PASS" if filter_ok and total > 0 else "FAIL" | |
| if not (filter_ok and total > 0): | |
| all_pass = False | |
| print(f" [{icon}] Paddy filter: {total} diseases, all Paddy: {filter_ok}") | |
| if ( | |
| name == "POST /treatment (English: Paddy Blast)" | |
| and passed | |
| and isinstance(body, dict) | |
| ): | |
| dname = body.get("disease_name", "") | |
| score = body.get("match_score", 0) | |
| exact = dname == "Paddy Blast" and score == 1.0 | |
| icon = "PASS" if exact else "FAIL" | |
| if not exact: | |
| all_pass = False | |
| print(f" [{icon}] English match: name={dname}, score={score}") | |
| if ( | |
| name == "POST /treatment (Hindi name)" | |
| and passed | |
| and isinstance(body, dict) | |
| ): | |
| dname = body.get("disease_name", "") | |
| score = body.get("match_score", 0) | |
| icon = "PASS" if score >= 0.9 else "FAIL" | |
| if score < 0.9: | |
| all_pass = False | |
| print(f" [{icon}] Hindi match: name={dname}, score={score}") | |
| if name == "GET /health" and passed and isinstance(body, dict): | |
| db_status = body.get("database", "unknown") | |
| icon = "PASS" if db_status == "connected" else "FAIL" | |
| if db_status != "connected": | |
| all_pass = False | |
| print(f" [{icon}] Database health: {db_status}") | |
| # --------------------------------------------------------------- | |
| # Response time check | |
| # --------------------------------------------------------------- | |
| print() | |
| print("-" * 80) | |
| print(" RESPONSE TIME VALIDATION (< 200ms)") | |
| print("-" * 80) | |
| slow = [(n, e) for n, p, s, e, b in results if e >= 200] | |
| if slow: | |
| all_pass = False | |
| for n, e in slow: | |
| print(f" [FAIL] {n}: {e:.1f}ms") | |
| else: | |
| print(f" [PASS] All {len(results)} requests completed in < 200ms") | |
| max_time = max(e for _, _, _, e, _ in results) | |
| avg_time = sum(e for _, _, _, e, _ in results) / len(results) | |
| print(f" Max: {max_time:.1f}ms | Avg: {avg_time:.1f}ms") | |
| # --------------------------------------------------------------- | |
| # Final verdict | |
| # --------------------------------------------------------------- | |
| print() | |
| print("=" * 80) | |
| passed_count = sum(1 for _, p, _, _, _ in results if p) | |
| total_count = len(results) | |
| print(f" RESULTS: {passed_count}/{total_count} endpoint tests passed") | |
| if all_pass: | |
| print(" CHECKPOINT 1: ALL TESTS PASSED") | |
| else: | |
| print(" CHECKPOINT 1: SOME TESTS FAILED") | |
| print("=" * 80) | |
| print() | |
| return 0 if all_pass else 1 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |