feat(api): add unified response format utilities (Section 1, Step 1.1-1.3) #1
108
TESTING-GUIDE.md
Normal file
108
TESTING-GUIDE.md
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
# Testing Guide for API Response Utilities
|
||||||
|
|
||||||
|
This guide helps you test the new unified response format utilities before merging the PR.
|
||||||
|
|
||||||
|
## Quick Test Script
|
||||||
|
|
||||||
|
Run the simple test script to verify basic functionality:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
python test_response_utilities.py
|
||||||
|
```
|
||||||
|
|
||||||
|
This will test:
|
||||||
|
- ✅ Import functionality
|
||||||
|
- ✅ `success_response()` function
|
||||||
|
- ✅ `error_response()` function
|
||||||
|
- ✅ `paginated_response()` function
|
||||||
|
|
||||||
|
## Django Unit Tests
|
||||||
|
|
||||||
|
Run the comprehensive unit tests:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
python manage.py test igny8_core.api.tests.test_response
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected output: All 15 test cases should pass.
|
||||||
|
|
||||||
|
## Test the /api/ping/ Endpoint
|
||||||
|
|
||||||
|
### Option 1: Using curl (if server is running)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test the ping endpoint
|
||||||
|
curl http://localhost:8011/api/ping/
|
||||||
|
|
||||||
|
# Expected response:
|
||||||
|
# {
|
||||||
|
# "success": true,
|
||||||
|
# "data": {
|
||||||
|
# "pong": true,
|
||||||
|
# "time": "2025-01-XX...",
|
||||||
|
# "version": "1.0.0"
|
||||||
|
# },
|
||||||
|
# "message": "API is live"
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 2: Using Postman or Browser
|
||||||
|
|
||||||
|
1. Start Django server: `python manage.py runserver`
|
||||||
|
2. Navigate to: `http://localhost:8000/api/ping/`
|
||||||
|
3. Verify response has `success: true` and `data` fields
|
||||||
|
|
||||||
|
### Option 3: Using Python requests
|
||||||
|
|
||||||
|
```python
|
||||||
|
import requests
|
||||||
|
|
||||||
|
response = requests.get('http://localhost:8011/api/ping/')
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
assert data['success'] == True
|
||||||
|
assert 'data' in data
|
||||||
|
assert 'pong' in data['data']
|
||||||
|
print("✅ Ping endpoint works!")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verification Checklist
|
||||||
|
|
||||||
|
Before merging the PR, verify:
|
||||||
|
|
||||||
|
- [ ] Quick test script passes (`python test_response_utilities.py`)
|
||||||
|
- [ ] Django unit tests pass (`python manage.py test igny8_core.api.tests.test_response`)
|
||||||
|
- [ ] `/api/ping/` endpoint returns unified format
|
||||||
|
- [ ] No linting errors
|
||||||
|
- [ ] All imports work correctly
|
||||||
|
|
||||||
|
## What to Look For
|
||||||
|
|
||||||
|
### ✅ Success Indicators:
|
||||||
|
- All tests pass
|
||||||
|
- Response has `success: true/false` field
|
||||||
|
- Response has `data` field (for success) or `error` field (for errors)
|
||||||
|
- No import errors
|
||||||
|
- No syntax errors
|
||||||
|
|
||||||
|
### ❌ Failure Indicators:
|
||||||
|
- Import errors
|
||||||
|
- Assertion errors in tests
|
||||||
|
- Missing fields in responses
|
||||||
|
- Syntax errors
|
||||||
|
|
||||||
|
## Next Steps After Testing
|
||||||
|
|
||||||
|
If all tests pass:
|
||||||
|
1. ✅ Merge the PR
|
||||||
|
2. Continue with Section 1, Task 2 (refactoring endpoints)
|
||||||
|
3. Or move to Section 2 (Authentication)
|
||||||
|
|
||||||
|
If tests fail:
|
||||||
|
1. Check error messages
|
||||||
|
2. Fix any issues
|
||||||
|
3. Re-test
|
||||||
|
4. Update PR with fixes
|
||||||
|
|
||||||
178
backend/test_response_utilities.py
Normal file
178
backend/test_response_utilities.py
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
"""
|
||||||
|
Quick Test Script for Response Utilities
|
||||||
|
|
||||||
|
Run this to verify the new response format utilities work correctly.
|
||||||
|
Usage: python test_response_utilities.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import django
|
||||||
|
|
||||||
|
# Setup Django
|
||||||
|
sys.path.insert(0, os.path.dirname(__file__))
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'igny8_core.settings')
|
||||||
|
django.setup()
|
||||||
|
|
||||||
|
from rest_framework import status
|
||||||
|
from igny8_core.api.response import success_response, error_response, paginated_response
|
||||||
|
|
||||||
|
|
||||||
|
def test_success_response():
|
||||||
|
"""Test success_response function"""
|
||||||
|
print("\n" + "="*60)
|
||||||
|
print("TEST 1: success_response()")
|
||||||
|
print("="*60)
|
||||||
|
|
||||||
|
# Test with data only
|
||||||
|
response = success_response(data={"id": 1, "name": "Test"})
|
||||||
|
data = response.data
|
||||||
|
print(f"✓ Status Code: {response.status_code}")
|
||||||
|
print(f"✓ Success: {data.get('success')}")
|
||||||
|
print(f"✓ Data: {data.get('data')}")
|
||||||
|
assert data['success'] == True, "Success should be True"
|
||||||
|
assert 'data' in data, "Should have data field"
|
||||||
|
print("✅ Test 1.1: success_response with data - PASSED")
|
||||||
|
|
||||||
|
# Test with data and message
|
||||||
|
response = success_response(
|
||||||
|
data={"id": 2, "name": "Test 2"},
|
||||||
|
message="Resource created successfully"
|
||||||
|
)
|
||||||
|
data = response.data
|
||||||
|
assert data['success'] == True, "Success should be True"
|
||||||
|
assert data.get('message') == "Resource created successfully", "Should have message"
|
||||||
|
print("✅ Test 1.2: success_response with data and message - PASSED")
|
||||||
|
|
||||||
|
# Test with custom status code
|
||||||
|
response = success_response(
|
||||||
|
data={"id": 3},
|
||||||
|
status_code=status.HTTP_201_CREATED
|
||||||
|
)
|
||||||
|
assert response.status_code == 201, "Status should be 201"
|
||||||
|
print("✅ Test 1.3: success_response with custom status - PASSED")
|
||||||
|
|
||||||
|
|
||||||
|
def test_error_response():
|
||||||
|
"""Test error_response function"""
|
||||||
|
print("\n" + "="*60)
|
||||||
|
print("TEST 2: error_response()")
|
||||||
|
print("="*60)
|
||||||
|
|
||||||
|
# Test with error only
|
||||||
|
response = error_response(error="Something went wrong")
|
||||||
|
data = response.data
|
||||||
|
print(f"✓ Status Code: {response.status_code}")
|
||||||
|
print(f"✓ Success: {data.get('success')}")
|
||||||
|
print(f"✓ Error: {data.get('error')}")
|
||||||
|
assert data['success'] == False, "Success should be False"
|
||||||
|
assert data['error'] == "Something went wrong", "Should have error message"
|
||||||
|
print("✅ Test 2.1: error_response with error only - PASSED")
|
||||||
|
|
||||||
|
# Test with error and errors dict
|
||||||
|
response = error_response(
|
||||||
|
error="Validation failed",
|
||||||
|
errors={"email": ["Invalid email format"], "password": ["Too short"]}
|
||||||
|
)
|
||||||
|
data = response.data
|
||||||
|
assert data['success'] == False, "Success should be False"
|
||||||
|
assert 'errors' in data, "Should have errors field"
|
||||||
|
assert len(data['errors']) == 2, "Should have 2 field errors"
|
||||||
|
print("✅ Test 2.2: error_response with errors dict - PASSED")
|
||||||
|
|
||||||
|
# Test with custom status code
|
||||||
|
response = error_response(
|
||||||
|
error="Not found",
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND
|
||||||
|
)
|
||||||
|
assert response.status_code == 404, "Status should be 404"
|
||||||
|
print("✅ Test 2.3: error_response with custom status - PASSED")
|
||||||
|
|
||||||
|
|
||||||
|
def test_paginated_response():
|
||||||
|
"""Test paginated_response function"""
|
||||||
|
print("\n" + "="*60)
|
||||||
|
print("TEST 3: paginated_response()")
|
||||||
|
print("="*60)
|
||||||
|
|
||||||
|
paginated_data = {
|
||||||
|
"count": 100,
|
||||||
|
"next": "http://api.example.com/endpoint/?page=2",
|
||||||
|
"previous": None,
|
||||||
|
"results": [{"id": 1}, {"id": 2}]
|
||||||
|
}
|
||||||
|
|
||||||
|
response = paginated_response(paginated_data)
|
||||||
|
data = response.data
|
||||||
|
print(f"✓ Status Code: {response.status_code}")
|
||||||
|
print(f"✓ Success: {data.get('success')}")
|
||||||
|
print(f"✓ Count: {data.get('count')}")
|
||||||
|
print(f"✓ Results: {len(data.get('results', []))} items")
|
||||||
|
assert data['success'] == True, "Success should be True"
|
||||||
|
assert data['count'] == 100, "Should have count"
|
||||||
|
assert 'results' in data, "Should have results"
|
||||||
|
assert len(data['results']) == 2, "Should have 2 results"
|
||||||
|
print("✅ Test 3.1: paginated_response - PASSED")
|
||||||
|
|
||||||
|
# Test with message
|
||||||
|
response = paginated_response(paginated_data, message="Keywords retrieved")
|
||||||
|
data = response.data
|
||||||
|
assert data.get('message') == "Keywords retrieved", "Should have message"
|
||||||
|
print("✅ Test 3.2: paginated_response with message - PASSED")
|
||||||
|
|
||||||
|
|
||||||
|
def test_imports():
|
||||||
|
"""Test that imports work correctly"""
|
||||||
|
print("\n" + "="*60)
|
||||||
|
print("TEST 4: Import Verification")
|
||||||
|
print("="*60)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from igny8_core.api import success_response, error_response, paginated_response
|
||||||
|
print("✅ All imports successful")
|
||||||
|
return True
|
||||||
|
except ImportError as e:
|
||||||
|
print(f"❌ Import failed: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run all tests"""
|
||||||
|
print("\n" + "="*60)
|
||||||
|
print("RESPONSE UTILITIES TEST SUITE")
|
||||||
|
print("="*60)
|
||||||
|
print("Testing unified response format utilities")
|
||||||
|
print("="*60)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Test imports
|
||||||
|
if not test_imports():
|
||||||
|
print("\n❌ Import test failed. Exiting.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Test functions
|
||||||
|
test_success_response()
|
||||||
|
test_error_response()
|
||||||
|
test_paginated_response()
|
||||||
|
|
||||||
|
print("\n" + "="*60)
|
||||||
|
print("✅ ALL TESTS PASSED!")
|
||||||
|
print("="*60)
|
||||||
|
print("\nNext steps:")
|
||||||
|
print("1. Run Django unit tests: python manage.py test igny8_core.api.tests.test_response")
|
||||||
|
print("2. Test /api/ping/ endpoint (if server is running)")
|
||||||
|
print("3. Merge PR when ready")
|
||||||
|
|
||||||
|
except AssertionError as e:
|
||||||
|
print(f"\n❌ Test failed: {e}")
|
||||||
|
sys.exit(1)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\n❌ Unexpected error: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
||||||
Reference in New Issue
Block a user