# API Testing Guide - Tenhal Healthcare Platform ## Setup for Testing ### 1. Install Required Packages ```bash pip install requests pytest pytest-django ``` ### 2. Start Development Server ```bash python manage.py runserver ``` ### 3. Create Test User (Django Shell) ```python python manage.py shell from core.models import User, Tenant # Create tenant tenant = Tenant.objects.create(name="Test Clinic") # Create test user user = User.objects.create_user( username='testuser', email='test@example.com', password='testpass123', tenant=tenant, role='DOCTOR' ) ``` ## Testing with Python Requests ### Basic Setup ```python import requests import json BASE_URL = 'http://localhost:8000/api/v1' # Login to get session session = requests.Session() login_response = session.post( 'http://localhost:8000/accounts/login/', data={'username': 'testuser', 'password': 'testpass123'} ) ``` ### Test 1: List Patients ```python def test_list_patients(): response = session.get(f'{BASE_URL}/patients/') assert response.status_code == 200 data = response.json() print(f"Found {data['count']} patients") return data # Run test patients = test_list_patients() ``` ### Test 2: Create Patient ```python def test_create_patient(): patient_data = { 'first_name_en': 'John', 'last_name_en': 'Doe', 'date_of_birth': '1990-01-01', 'gender': 'MALE', 'phone': '+966501234567', 'email': 'john.doe@example.com' } response = session.post( f'{BASE_URL}/patients/', json=patient_data ) assert response.status_code == 201 patient = response.json() print(f"Created patient: {patient['id']}") return patient # Run test new_patient = test_create_patient() ``` ### Test 3: Get Patient Details ```python def test_get_patient(patient_id): response = session.get(f'{BASE_URL}/patients/{patient_id}/') assert response.status_code == 200 patient = response.json() print(f"Patient: {patient['full_name']}") return patient # Run test patient_details = test_get_patient(new_patient['id']) ``` ### Test 4: Search Patients ```python def test_search_patients(query): response = session.get( f'{BASE_URL}/patients/', params={'search': query} ) assert response.status_code == 200 data = response.json() print(f"Found {data['count']} patients matching '{query}'") return data # Run test search_results = test_search_patients('john') ``` ### Test 5: Book Appointment ```python def test_book_appointment(patient_id, clinic_id, provider_id): appointment_data = { 'patient': patient_id, 'clinic': clinic_id, 'provider': provider_id, 'service_type': 'CONSULTATION', 'scheduled_date': '2025-10-15', 'scheduled_time': '10:00:00', 'duration': 30, 'notes': 'First visit' } response = session.post( f'{BASE_URL}/appointments/', json=appointment_data ) assert response.status_code == 201 appointment = response.json() print(f"Booked appointment: {appointment['appointment_number']}") return appointment # Run test (replace with actual IDs) # appointment = test_book_appointment(patient_id, clinic_id, provider_id) ``` ### Test 6: Confirm Appointment ```python def test_confirm_appointment(appointment_id): response = session.post( f'{BASE_URL}/appointments/{appointment_id}/confirm/', json={'method': 'SMS'} ) assert response.status_code == 200 appointment = response.json() print(f"Confirmed appointment: {appointment['status']}") return appointment # Run test # confirmed = test_confirm_appointment(appointment['id']) ``` ### Test 7: Create Invoice ```python def test_create_invoice(patient_id, service_id): invoice_data = { 'patient': patient_id, 'issue_date': '2025-10-13', 'due_date': '2025-10-20', 'subtotal': '500.00', 'tax': '75.00', 'discount': '0.00', 'line_items': [ { 'service': service_id, 'description': 'Medical Consultation', 'quantity': 1, 'unit_price': '500.00' } ] } response = session.post( f'{BASE_URL}/invoices/', json=invoice_data ) assert response.status_code == 201 invoice = response.json() print(f"Created invoice: {invoice['invoice_number']}") return invoice # Run test # invoice = test_create_invoice(patient_id, service_id) ``` ### Test 8: Record Payment ```python def test_record_payment(invoice_id): payment_data = { 'invoice': invoice_id, 'payment_date': '2025-10-13', 'amount': '575.00', 'method': 'CARD', 'transaction_id': 'TXN123456', 'reference': 'Card ending 1234' } response = session.post( f'{BASE_URL}/payments/', json=payment_data ) assert response.status_code == 201 payment = response.json() print(f"Recorded payment: {payment['id']}") return payment # Run test # payment = test_record_payment(invoice['id']) ``` ### Test 9: Create Referral ```python def test_create_referral(patient_id, from_clinic_id, to_clinic_id): referral_data = { 'patient': patient_id, 'from_clinic': from_clinic_id, 'to_clinic': to_clinic_id, 'reason': 'Patient requires ABA assessment', 'clinical_summary': '3-year-old with speech delay', 'urgency': 'ROUTINE' } response = session.post( f'{BASE_URL}/referrals/', json=referral_data ) assert response.status_code == 201 referral = response.json() print(f"Created referral: {referral['id']}") return referral # Run test # referral = test_create_referral(patient_id, from_clinic_id, to_clinic_id) ``` ### Test 10: Accept Referral ```python def test_accept_referral(referral_id): response = session.post( f'{BASE_URL}/referrals/{referral_id}/accept/', json={'response_notes': 'Referral accepted. Will schedule assessment.'} ) assert response.status_code == 200 referral = response.json() print(f"Accepted referral: {referral['status']}") return referral # Run test # accepted = test_accept_referral(referral['id']) ``` ## Testing with cURL ### List Patients ```bash curl -X GET http://localhost:8000/api/v1/patients/ \ -H "Cookie: sessionid=your-session-id" ``` ### Create Patient ```bash curl -X POST http://localhost:8000/api/v1/patients/ \ -H "Content-Type: application/json" \ -H "Cookie: sessionid=your-session-id" \ -d '{ "first_name_en": "Jane", "last_name_en": "Smith", "date_of_birth": "1985-05-15", "gender": "FEMALE", "phone": "+966509876543" }' ``` ### Book Appointment ```bash curl -X POST http://localhost:8000/api/v1/appointments/ \ -H "Content-Type: application/json" \ -H "Cookie: sessionid=your-session-id" \ -d '{ "patient": "patient-uuid", "clinic": "clinic-uuid", "provider": "provider-uuid", "scheduled_date": "2025-10-15", "scheduled_time": "14:00:00", "duration": 30 }' ``` ### Get Today's Appointments ```bash curl -X GET http://localhost:8000/api/v1/appointments/today/ \ -H "Cookie: sessionid=your-session-id" ``` ### Get Appointment Statistics ```bash curl -X GET http://localhost:8000/api/v1/appointments/statistics/ \ -H "Cookie: sessionid=your-session-id" ``` ## Complete Test Suite ```python import requests import json from datetime import date, timedelta class TenhalAPITester: def __init__(self, base_url='http://localhost:8000'): self.base_url = base_url self.api_url = f'{base_url}/api/v1' self.session = requests.Session() def login(self, username, password): """Login and establish session""" response = self.session.post( f'{self.base_url}/accounts/login/', data={'username': username, 'password': password} ) return response.status_code == 200 def test_patient_workflow(self): """Test complete patient workflow""" print("\n=== Testing Patient Workflow ===") # 1. Create patient patient_data = { 'first_name_en': 'Test', 'last_name_en': 'Patient', 'date_of_birth': '2020-01-01', 'gender': 'MALE', 'phone': '+966501111111' } response = self.session.post(f'{self.api_url}/patients/', json=patient_data) assert response.status_code == 201 patient = response.json() print(f"✓ Created patient: {patient['mrn']}") # 2. Get patient details response = self.session.get(f"{self.api_url}/patients/{patient['id']}/") assert response.status_code == 200 print(f"✓ Retrieved patient details") # 3. Search for patient response = self.session.get(f"{self.api_url}/patients/", params={'search': 'Test'}) assert response.status_code == 200 print(f"✓ Searched patients") return patient def test_appointment_workflow(self, patient_id, clinic_id, provider_id): """Test complete appointment workflow""" print("\n=== Testing Appointment Workflow ===") # 1. Book appointment appointment_data = { 'patient': patient_id, 'clinic': clinic_id, 'provider': provider_id, 'scheduled_date': str(date.today() + timedelta(days=1)), 'scheduled_time': '10:00:00', 'duration': 30 } response = self.session.post(f'{self.api_url}/appointments/', json=appointment_data) assert response.status_code == 201 appointment = response.json() print(f"✓ Booked appointment: {appointment['appointment_number']}") # 2. Confirm appointment response = self.session.post( f"{self.api_url}/appointments/{appointment['id']}/confirm/", json={'method': 'SMS'} ) assert response.status_code == 200 print(f"✓ Confirmed appointment") # 3. Mark arrived response = self.session.post(f"{self.api_url}/appointments/{appointment['id']}/arrive/") assert response.status_code == 200 print(f"✓ Marked patient arrived") # 4. Start appointment response = self.session.post(f"{self.api_url}/appointments/{appointment['id']}/start/") assert response.status_code == 200 print(f"✓ Started appointment") # 5. Complete appointment response = self.session.post(f"{self.api_url}/appointments/{appointment['id']}/complete/") assert response.status_code == 200 print(f"✓ Completed appointment") return appointment def test_finance_workflow(self, patient_id, service_id): """Test complete finance workflow""" print("\n=== Testing Finance Workflow ===") # 1. Create invoice invoice_data = { 'patient': patient_id, 'issue_date': str(date.today()), 'due_date': str(date.today() + timedelta(days=7)), 'subtotal': '500.00', 'tax': '75.00', 'discount': '0.00', 'line_items': [{ 'service': service_id, 'description': 'Test Service', 'quantity': 1, 'unit_price': '500.00' }] } response = self.session.post(f'{self.api_url}/invoices/', json=invoice_data) assert response.status_code == 201 invoice = response.json() print(f"✓ Created invoice: {invoice['invoice_number']}") # 2. Issue invoice response = self.session.post(f"{self.api_url}/invoices/{invoice['id']}/issue/") assert response.status_code == 200 print(f"✓ Issued invoice") # 3. Record payment payment_data = { 'invoice': invoice['id'], 'payment_date': str(date.today()), 'amount': '575.00', 'method': 'CASH' } response = self.session.post(f'{self.api_url}/payments/', json=payment_data) assert response.status_code == 201 print(f"✓ Recorded payment") # 4. Process payment payment = response.json() response = self.session.post(f"{self.api_url}/payments/{payment['id']}/process/") assert response.status_code == 200 print(f"✓ Processed payment") return invoice def test_referral_workflow(self, patient_id, from_clinic_id, to_clinic_id): """Test complete referral workflow""" print("\n=== Testing Referral Workflow ===") # 1. Create referral referral_data = { 'patient': patient_id, 'from_clinic': from_clinic_id, 'to_clinic': to_clinic_id, 'reason': 'Test referral', 'urgency': 'ROUTINE' } response = self.session.post(f'{self.api_url}/referrals/', json=referral_data) assert response.status_code == 201 referral = response.json() print(f"✓ Created referral") # 2. Accept referral response = self.session.post( f"{self.api_url}/referrals/{referral['id']}/accept/", json={'response_notes': 'Accepted'} ) assert response.status_code == 200 print(f"✓ Accepted referral") # 3. Complete referral response = self.session.post(f"{self.api_url}/referrals/{referral['id']}/complete/") assert response.status_code == 200 print(f"✓ Completed referral") return referral def run_all_tests(self, clinic_id, provider_id, service_id): """Run all test workflows""" print("\n" + "="*50) print("TENHAL API TEST SUITE") print("="*50) # Test patient workflow patient = self.test_patient_workflow() # Test appointment workflow appointment = self.test_appointment_workflow( patient['id'], clinic_id, provider_id ) # Test finance workflow invoice = self.test_finance_workflow(patient['id'], service_id) # Test referral workflow (need two clinics) # referral = self.test_referral_workflow(patient['id'], clinic_id, clinic_id) print("\n" + "="*50) print("ALL TESTS PASSED ✓") print("="*50) # Usage if __name__ == '__main__': tester = TenhalAPITester() # Login if tester.login('testuser', 'testpass123'): print("✓ Logged in successfully") # Run tests (replace with actual IDs) # tester.run_all_tests( # clinic_id='your-clinic-uuid', # provider_id='your-provider-uuid', # service_id='your-service-uuid' # ) else: print("✗ Login failed") ``` ## Performance Testing ```python import time import statistics def performance_test(session, endpoint, iterations=100): """Test API endpoint performance""" times = [] for i in range(iterations): start = time.time() response = session.get(f'{BASE_URL}{endpoint}') end = time.time() times.append(end - start) print(f"\nPerformance Test: {endpoint}") print(f"Iterations: {iterations}") print(f"Average: {statistics.mean(times):.3f}s") print(f"Median: {statistics.median(times):.3f}s") print(f"Min: {min(times):.3f}s") print(f"Max: {max(times):.3f}s") # Run performance tests performance_test(session, '/patients/', iterations=50) performance_test(session, '/appointments/', iterations=50) ``` ## Error Handling Tests ```python def test_error_handling(): """Test API error responses""" # Test 404 response = session.get(f'{BASE_URL}/patients/invalid-uuid/') assert response.status_code == 404 print("✓ 404 error handled correctly") # Test 400 (validation error) response = session.post(f'{BASE_URL}/patients/', json={}) assert response.status_code == 400 print("✓ 400 validation error handled correctly") # Test unauthorized unauthorized_session = requests.Session() response = unauthorized_session.get(f'{BASE_URL}/patients/') assert response.status_code in [401, 403] print("✓ Unauthorized access blocked") test_error_handling() ``` ## Conclusion This testing guide provides comprehensive examples for testing all major API endpoints. Adapt the test data (UUIDs, dates, etc.) to match your actual database records. For automated testing in CI/CD, consider using pytest with pytest-django for integration tests.