FarmerHelp / backend /tests /checkpoint1.py
Gankit12's picture
All Code
b64de39
Raw
History Blame Contribute Delete
8.14 kB
"""
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())