Spaces:
Sleeping
Sleeping
| """ | |
| Comprehensive API Testing Script | |
| Tests all endpoints with realistic medical scenarios | |
| """ | |
| import requests | |
| import json | |
| import time | |
| from typing import Dict, List | |
| import os | |
| class HealthAPITester: | |
| """Test suite for AI Health Diagnostics API""" | |
| def __init__(self, base_url="http://localhost:8000"): | |
| self.base_url = base_url | |
| self.user_ids = [] | |
| self.test_results = [] | |
| def print_section(self, title: str): | |
| """Print formatted section header""" | |
| print("\n" + "=" * 70) | |
| print(f" {title}") | |
| print("=" * 70) | |
| def print_result(self, test_name: str, passed: bool, details: str = ""): | |
| """Print test result""" | |
| status = "✅ PASS" if passed else "❌ FAIL" | |
| print(f"{status} | {test_name}") | |
| if details: | |
| print(f" {details}") | |
| self.test_results.append((test_name, passed)) | |
| def test_health_check(self): | |
| """Test root endpoint""" | |
| self.print_section("1. Health Check") | |
| try: | |
| response = requests.get(f"{self.base_url}/") | |
| passed = response.status_code == 200 | |
| details = response.json().get("status", "No status") | |
| self.print_result("API Health Check", passed, details) | |
| return passed | |
| except Exception as e: | |
| self.print_result("API Health Check", False, str(e)) | |
| return False | |
| def test_create_profiles(self): | |
| """Test profile creation with various user types""" | |
| self.print_section("2. User Profile Creation") | |
| test_profiles = [ | |
| { | |
| "name": "Young Adult - No Conditions", | |
| "data": { | |
| "age": 25, | |
| "gender": "female", | |
| "allergies": "", | |
| "conditions": "" | |
| } | |
| }, | |
| { | |
| "name": "Middle-aged - Multiple Allergies", | |
| "data": { | |
| "age": 45, | |
| "gender": "male", | |
| "allergies": "penicillin, shellfish", | |
| "conditions": "hypertension" | |
| } | |
| }, | |
| { | |
| "name": "Senior - Chronic Conditions", | |
| "data": { | |
| "age": 68, | |
| "gender": "female", | |
| "allergies": "sulfa drugs", | |
| "conditions": "diabetes, arthritis" | |
| } | |
| }, | |
| { | |
| "name": "Child Profile", | |
| "data": { | |
| "age": 8, | |
| "gender": "male", | |
| "allergies": "peanuts", | |
| "conditions": "asthma" | |
| } | |
| } | |
| ] | |
| for profile in test_profiles: | |
| try: | |
| response = requests.post( | |
| f"{self.base_url}/create-profile", | |
| json=profile["data"] | |
| ) | |
| if response.status_code == 200: | |
| result = response.json() | |
| user_id = result["data"]["user_id"] | |
| self.user_ids.append({ | |
| "name": profile["name"], | |
| "id": user_id, | |
| "profile": profile["data"] | |
| }) | |
| self.print_result( | |
| f"Create Profile: {profile['name']}", | |
| True, | |
| f"User ID: {user_id[:8]}..." | |
| ) | |
| else: | |
| self.print_result( | |
| f"Create Profile: {profile['name']}", | |
| False, | |
| f"Status: {response.status_code}" | |
| ) | |
| except Exception as e: | |
| self.print_result( | |
| f"Create Profile: {profile['name']}", | |
| False, | |
| str(e) | |
| ) | |
| def test_symptom_analysis(self): | |
| """Test symptom checking with realistic scenarios""" | |
| self.print_section("3. Symptom Analysis") | |
| test_cases = [ | |
| { | |
| "name": "Common Cold Symptoms", | |
| "symptoms": "runny nose, cough, sore throat, mild fever, fatigue", | |
| "expected_conditions": ["Common Cold", "Influenza"] | |
| }, | |
| { | |
| "name": "Flu-like Symptoms", | |
| "symptoms": "high fever, severe headache, body aches, cough, fatigue", | |
| "expected_conditions": ["Influenza", "COVID-19"] | |
| }, | |
| { | |
| "name": "Food Poisoning", | |
| "symptoms": "nausea, vomiting, diarrhea, abdominal cramps", | |
| "expected_conditions": ["Gastroenteritis", "Food Poisoning"] | |
| }, | |
| { | |
| "name": "Migraine Symptoms", | |
| "symptoms": "severe headache, sensitivity to light, nausea", | |
| "expected_conditions": ["Migraine"] | |
| }, | |
| { | |
| "name": "Allergic Reaction", | |
| "symptoms": "rash, itching, swelling, redness", | |
| "expected_conditions": ["Allergic Reaction"] | |
| }, | |
| { | |
| "name": "Respiratory Infection", | |
| "symptoms": "persistent cough, shortness of breath, chest pain, fever", | |
| "expected_conditions": ["Pneumonia", "Bronchitis"] | |
| }, | |
| { | |
| "name": "Emergency Symptoms", | |
| "symptoms": "severe chest pain, difficulty breathing, confusion", | |
| "expected_conditions": ["Cardiac Issue", "Heart Condition"] | |
| } | |
| ] | |
| if not self.user_ids: | |
| self.print_result("Symptom Analysis", False, "No user profiles available") | |
| return | |
| user = self.user_ids[0] # Use first user | |
| for case in test_cases: | |
| try: | |
| response = requests.post( | |
| f"{self.base_url}/symptom-check", | |
| json={ | |
| "user_id": user["id"], | |
| "symptoms": case["symptoms"] | |
| } | |
| ) | |
| if response.status_code == 200: | |
| result = response.json() | |
| conditions = result["data"]["possible_conditions"] | |
| # Check if any expected condition is in top 3 results | |
| detected = [c["condition"] for c in conditions[:3]] | |
| found_match = any( | |
| exp in detected | |
| for exp in case["expected_conditions"] | |
| ) | |
| if conditions: | |
| top_condition = conditions[0] | |
| details = ( | |
| f"{top_condition['condition']} " | |
| f"(confidence: {top_condition['confidence']:.2f}, " | |
| f"urgency: {top_condition['urgency']})" | |
| ) | |
| self.print_result( | |
| f"Analyze: {case['name']}", | |
| True, | |
| details | |
| ) | |
| else: | |
| self.print_result( | |
| f"Analyze: {case['name']}", | |
| False, | |
| "No conditions detected" | |
| ) | |
| else: | |
| self.print_result( | |
| f"Analyze: {case['name']}", | |
| False, | |
| f"Status: {response.status_code}" | |
| ) | |
| time.sleep(0.5) # Rate limiting | |
| except Exception as e: | |
| self.print_result( | |
| f"Analyze: {case['name']}", | |
| False, | |
| str(e) | |
| ) | |
| def test_image_analysis(self): | |
| """Test image analysis (with synthetic images)""" | |
| self.print_section("4. Medical Image Analysis") | |
| # Create sample test images if they don't exist | |
| test_images = self._create_test_images() | |
| if not self.user_ids: | |
| self.print_result("Image Analysis", False, "No user profiles available") | |
| return | |
| user = self.user_ids[0] | |
| for image_file, image_type in test_images: | |
| if not os.path.exists(image_file): | |
| continue | |
| try: | |
| with open(image_file, 'rb') as f: | |
| files = {'file': (image_file, f, 'image/jpeg')} | |
| data = { | |
| 'user_id': user["id"], | |
| 'image_type': image_type | |
| } | |
| response = requests.post( | |
| f"{self.base_url}/analyze-image", | |
| files=files, | |
| data=data | |
| ) | |
| if response.status_code == 200: | |
| result = response.json() | |
| analysis = result["data"] | |
| details = ( | |
| f"{analysis['detected_condition']} " | |
| f"(confidence: {analysis['confidence']:.2f}, " | |
| f"urgency: {analysis['urgency']})" | |
| ) | |
| self.print_result( | |
| f"Analyze Image: {os.path.basename(image_file)}", | |
| True, | |
| details | |
| ) | |
| else: | |
| self.print_result( | |
| f"Analyze Image: {os.path.basename(image_file)}", | |
| False, | |
| f"Status: {response.status_code}" | |
| ) | |
| time.sleep(0.5) | |
| except Exception as e: | |
| self.print_result( | |
| f"Analyze Image: {os.path.basename(image_file)}", | |
| False, | |
| str(e) | |
| ) | |
| def test_user_history(self): | |
| """Test retrieving user history""" | |
| self.print_section("5. User History Retrieval") | |
| if not self.user_ids: | |
| self.print_result("User History", False, "No user profiles available") | |
| return | |
| for user in self.user_ids[:2]: # Test first 2 users | |
| try: | |
| response = requests.get( | |
| f"{self.base_url}/user-history/{user['id']}" | |
| ) | |
| if response.status_code == 200: | |
| result = response.json() | |
| data = result["data"] | |
| symptom_count = len(data.get("symptom_checks", [])) | |
| image_count = len(data.get("image_analyses", [])) | |
| details = ( | |
| f"{symptom_count} symptom checks, " | |
| f"{image_count} image analyses" | |
| ) | |
| self.print_result( | |
| f"History: {user['name']}", | |
| True, | |
| details | |
| ) | |
| else: | |
| self.print_result( | |
| f"History: {user['name']}", | |
| False, | |
| f"Status: {response.status_code}" | |
| ) | |
| except Exception as e: | |
| self.print_result( | |
| f"History: {user['name']}", | |
| False, | |
| str(e) | |
| ) | |
| def test_edge_cases(self): | |
| """Test edge cases and error handling""" | |
| self.print_section("6. Edge Cases & Error Handling") | |
| # Test invalid user ID | |
| try: | |
| response = requests.post( | |
| f"{self.base_url}/symptom-check", | |
| json={ | |
| "user_id": "invalid-user-id-12345", | |
| "symptoms": "headache" | |
| } | |
| ) | |
| passed = response.status_code == 404 | |
| self.print_result( | |
| "Invalid User ID", | |
| passed, | |
| "Correctly rejected" if passed else "Should return 404" | |
| ) | |
| except Exception as e: | |
| self.print_result("Invalid User ID", False, str(e)) | |
| # Test empty symptoms | |
| if self.user_ids: | |
| try: | |
| response = requests.post( | |
| f"{self.base_url}/symptom-check", | |
| json={ | |
| "user_id": self.user_ids[0]["id"], | |
| "symptoms": "" | |
| } | |
| ) | |
| result = response.json() | |
| passed = response.status_code == 200 | |
| self.print_result( | |
| "Empty Symptoms", | |
| passed, | |
| "Handled gracefully" if passed else "Should handle empty input" | |
| ) | |
| except Exception as e: | |
| self.print_result("Empty Symptoms", False, str(e)) | |
| def _create_test_images(self) -> List[tuple]: | |
| """Create simple test images""" | |
| try: | |
| from PIL import Image, ImageDraw | |
| import numpy as np | |
| os.makedirs("test_images", exist_ok=True) | |
| images = [] | |
| # Create a simple test image | |
| img = Image.new('RGB', (224, 224), color='lightpink') | |
| draw = ImageDraw.Draw(img) | |
| draw.ellipse([50, 50, 174, 174], fill='red', outline='darkred') | |
| img.save("test_images/skin_rash.jpg") | |
| images.append(("test_images/skin_rash.jpg", "skin")) | |
| return images | |
| except: | |
| return [] | |
| def print_summary(self): | |
| """Print test summary""" | |
| self.print_section("Test Summary") | |
| total = len(self.test_results) | |
| passed = sum(1 for _, result in self.test_results if result) | |
| failed = total - passed | |
| print(f"\nTotal Tests: {total}") | |
| print(f"✅ Passed: {passed}") | |
| print(f"❌ Failed: {failed}") | |
| print(f"Success Rate: {(passed/total*100) if total > 0 else 0:.1f}%") | |
| if failed > 0: | |
| print("\n⚠️ Failed Tests:") | |
| for name, result in self.test_results: | |
| if not result: | |
| print(f" - {name}") | |
| print("\n" + "=" * 70) | |
| def run_all_tests(self): | |
| """Run complete test suite""" | |
| print("\n🧪 AI Health Diagnostics API - Comprehensive Test Suite") | |
| print(f"🌐 Testing endpoint: {self.base_url}") | |
| # Run tests in order | |
| if not self.test_health_check(): | |
| print("\n❌ API is not running. Start server with:") | |
| print(" uvicorn main:app --reload") | |
| return | |
| self.test_create_profiles() | |
| self.test_symptom_analysis() | |
| self.test_image_analysis() | |
| self.test_user_history() | |
| self.test_edge_cases() | |
| # Print summary | |
| self.print_summary() | |
| def main(): | |
| """Main test runner""" | |
| import sys | |
| base_url = "http://localhost:8000" | |
| if len(sys.argv) > 1: | |
| base_url = sys.argv[1] | |
| tester = HealthAPITester(base_url) | |
| tester.run_all_tests() | |
| if __name__ == "__main__": | |
| main() |