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

17 KiB

API Testing Guide - Tenhal Healthcare Platform

Setup for Testing

1. Install Required Packages

pip install requests pytest pytest-django

2. Start Development Server

python manage.py runserver

3. Create Test User (Django Shell)

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

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

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

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

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

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

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

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

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

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

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

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

curl -X GET http://localhost:8000/api/v1/patients/ \
  -H "Cookie: sessionid=your-session-id"

Create Patient

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

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

curl -X GET http://localhost:8000/api/v1/appointments/today/ \
  -H "Cookie: sessionid=your-session-id"

Get Appointment Statistics

curl -X GET http://localhost:8000/api/v1/appointments/statistics/ \
  -H "Cookie: sessionid=your-session-id"

Complete Test Suite

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

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

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.