agdar/API_TESTING_GUIDE.md
2025-11-02 14:35:35 +03:00

589 lines
17 KiB
Markdown

# 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.