The Cougar Mountain Zoo (CMZ) API uses a comprehensive integration test framework designed for Test-Driven Development (TDD) against Jira ticket requirements. This framework validates the API implementation against the comprehensive API Validation Epic and ensures all business requirements are properly implemented.
backend/api/
├── openapi_spec.yaml # OpenAPI 3.0 specification (source of truth)
├── src/main/python/
│ ├── openapi_server/
│ │ ├── impl/ # Business logic implementation
│ │ ├── controllers/ # Generated API controllers
│ │ ├── models/ # Generated data models
│ │ └── test/ # Generated test stubs
│ ├── tests/ # Integration test framework
│ │ ├── conftest.py # Test configuration and fixtures
│ │ ├── integration/
│ │ │ ├── test_api_validation_epic.py # Jira ticket validation tests
│ │ │ └── test_endpoints.py # Endpoint-specific tests
│ │ └── README.md # Test framework documentation
│ ├── requirements.txt # Production dependencies
│ ├── requirements-test.txt # Test dependencies
│ ├── pytest.ini # Test configuration
│ └── run_integration_tests.py # Test runner script
├── Dockerfile # Container definition
└── tox.ini # Test configuration
The integration test framework is specifically designed to validate API implementation against Jira ticket requirements from the API Validation Epic (PR003946-61).
- Test Configuration (
conftest.py): Provides fixtures for DynamoDB mocking, authentication, sample data, and validation helpers - API Validation Tests (
test_api_validation_epic.py): Direct mapping to 26 Jira tickets (PR003946-66 through PR003946-91) - Endpoint Tests (
test_endpoints.py): Comprehensive endpoint testing by functional area - Test Runner (
run_integration_tests.py): TDD-enabled test execution with file watching
The test framework maps directly to Jira tickets from the API Validation Epic:
| Ticket Range | Test Class | Validation Focus |
|---|---|---|
| PR003946-66-68 | TestSoftDeleteSemantics | Soft-delete enforcement across entities |
| PR003946-69-70 | TestIDValidation | Server-generated IDs, reject client IDs |
| PR003946-71-72, 87-88 | TestAuthenticationValidation | JWT tokens, roles, password policy |
| PR003946-73-75 | TestDataIntegrityValidation | Foreign keys, data consistency |
| PR003946-79-80 | TestFamilyManagementValidation | Family membership constraints |
| PR003946-81-82 | TestPaginationValidation | Pagination and filtering |
| PR003946-83-85 | TestAnalyticsValidation | Time windows, log levels, metrics |
| PR003946-86 | TestBillingValidation | Period format validation |
| PR003946-89, 91 | TestInputValidation | Media upload, message length limits |
| PR003946-90 | TestErrorHandlingValidation | Consistent Error schema |
The framework supports a complete TDD workflow:
- Red Phase: Write failing tests for Jira requirements
- Green Phase: Implement minimal code to pass tests
- Refactor Phase: Improve implementation while maintaining test coverage
- Python 3.9+
- Docker (for containerized development)
- AWS CLI configured for DynamoDB access
-
Install Production Dependencies
cd backend/api/src/main/python pip install -r requirements.txt -
Install Test Dependencies
pip install -r requirements-test.txt
-
Verify Installation
python -m pytest --version python run_integration_tests.py --help
# Regenerate API from OpenAPI spec
make generate-api
# Build and run API server
make build-api && make run-api
# In another terminal, run tests
python run_integration_tests.py --tdd# Example: Implementing password policy validation (PR003946-87)
# Add test to test_api_validation_epic.py
def test_pr003946_87_password_policy_enforcement(self, client, validation_helper, data_factory):
"""PR003946-87: Password policy enforcement with configurable rules"""
# Test weak password
auth_data = data_factory.create_auth_request(password="123") # Too short
response = client.post('/auth', json=auth_data)
assert response.status_code == 400
data = response.json()
validation_helper.assert_error_schema(data, "invalid_password")
assert "password" in data.get("details", {}), "Should provide password policy guidance"
# Run specific test
python run_integration_tests.py --ticket PR003946-87# Update impl/auth.py or similar to implement password validation
def validate_password(password: str) -> bool:
"""Validate password meets policy requirements"""
if len(password) < 6:
return False
# Add additional validation rules
return True# Run all tests to ensure no regression
python run_integration_tests.py --coverage
# Generate comprehensive report
python run_integration_tests.py --report# Test specific ticket requirements
python run_integration_tests.py --ticket PR003946-90
# Test authentication requirements
python run_integration_tests.py --auth
# Test soft delete requirements
python run_integration_tests.py --soft-delete# Test all endpoint validations
python run_integration_tests.py --endpoints
# Test API validation epic
python run_integration_tests.py --validation
# Test data integrity
python run_integration_tests.py --data-integrityTests are organized with pytest markers for easy filtering:
integration: All integration testsvalidation: Jira ticket validation testsauth: Authentication and authorization testsdata_integrity: Data integrity and foreign key testssoft_delete: Soft delete functionality testspagination: Pagination and filtering testserror_handling: Error response format tests
# Run only authentication tests
pytest tests/integration/ -m "auth" -v
# Run data integrity tests
pytest tests/integration/ -m "data_integrity" -v
# Run tests that require database
pytest tests/integration/ -m "requires_db" -v
# Run all except slow tests
pytest tests/integration/ -m "not slow" -vFollow the Arrange-Act-Assert pattern:
def test_user_creation_validation(self, client, validation_helper, data_factory):
# Arrange: Set up test data
user_data = data_factory.create_user_request(email="invalid-email")
# Act: Make API call
response = client.post('/user', json=user_data)
# Assert: Validate response
assert response.status_code == 400
validation_helper.assert_error_schema(response.json(), "invalid_email")def test_animal_details(self, client, db_helper, sample_animal, validation_helper):
# Use fixtures for consistent test data
animal = db_helper.insert_test_animal(sample_animal)
response = client.get(f'/animal_details?animalId={animal["animalId"]}')
if response.status_code == 200:
validation_helper.assert_audit_fields(response.json())def test_pr003946_69_server_generated_ids(self, client, validation_helper):
"""PR003946-69: Server generates all entity IDs, rejects client-provided IDs"""
response = client.post('/animal', json=animal_data)
if response.status_code == 201:
# Feature implemented correctly
validation_helper.assert_server_generated_id(response.json(), 'animalId')
else:
# Document current behavior - implementation needed
assert response.status_code in [404, 501]name: CMZ API Tests
on: [push, pull_request]
jobs:
integration-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install dependencies
run: |
cd backend/api/src/main/python
pip install -r requirements.txt
pip install -r requirements-test.txt
- name: Run integration tests
run: |
cd backend/api/src/main/python
python run_integration_tests.py --junit --html-report --coverage
- name: Upload test reports
uses: actions/upload-artifact@v3
if: always()
with:
name: test-reports
path: backend/api/src/main/python/reports/# Add to existing Dockerfile for test stage
FROM python:3.9 AS test
WORKDIR /app
COPY backend/api/src/main/python/ .
RUN pip install -r requirements.txt -r requirements-test.txt
# Run tests during build
RUN python run_integration_tests.py --report
# Copy test reports to final stage if needed
FROM python:3.9
COPY --from=test /app/reports/ /app/reports/# Complete regeneration and deployment cycle
make generate-api && make build-api && make run-api
# Monitor running container
make logs-api
# Run tests against running API
python run_integration_tests.py --coverage
# Stop and cleanup
make stop-api && make clean-api# TDD mode - watch for changes and re-run tests
python run_integration_tests.py --tdd
# Test specific implementation areas
python run_integration_tests.py --auth --verbose
# Generate reports for documentation
python run_integration_tests.py --reportAll tests validate that error responses follow the consistent Error schema (PR003946-90):
def validate_error_response(response):
"""Validate error follows required schema"""
data = response.json()
# Required fields
assert "code" in data
assert "message" in data
assert isinstance(data["code"], str)
assert isinstance(data["message"], str)
# Optional field-level details
if "details" in data:
assert isinstance(data["details"], dict)All entities must have proper audit fields:
def validate_audit_fields(entity_data):
"""Validate entity has required audit fields"""
assert "created" in entity_data
assert "modified" in entity_data
assert "softDelete" in entity_data
for audit_field in ["created", "modified"]:
if entity_data[audit_field]:
assert "at" in entity_data[audit_field]
assert "by" in entity_data[audit_field]-
DynamoDB Connection Errors
# Ensure moto is installed correctly pip install --upgrade 'moto[dynamodb]'
-
Import Errors
# Add project root to Python path export PYTHONPATH="${PYTHONPATH}:$(pwd)"
-
Test Discovery Issues
# Verify test discovery pytest --collect-only tests/integration/ -
API Server Not Running
# Start API server in separate terminal make run-api # Or run tests against mock (default behavior) python run_integration_tests.py
# Run with verbose debugging
pytest tests/integration/ -vvv --tb=long
# Run single test with debugger
pytest tests/integration/test_endpoints.py::TestAuthEndpoints::test_auth_validation -vvv --pdb
# Show all fixtures
pytest --fixtures tests/integration/Based on analysis of Jira tickets vs current implementation:
- Basic OpenAPI specification
- Generated controllers and models
- Basic CRUD operations structure
- Docker containerization
- DynamoDB integration patterns
- Error schema structure (exists but not consistently used)
- Audit fields (schema exists but no enforcement)
- Authentication endpoints (basic structure, no validation)
- Comprehensive input validation (26 validation tickets)
- Role-based access control enforcement
- Soft-delete semantics enforcement
- Server-generated ID validation
- Password policy enforcement
- Foreign key constraint validation
- Pagination parameter validation
- Error Schema Consistency (PR003946-90) - Affects all endpoints
- Authentication Framework (PR003946-71, 72, 87, 88) - Security foundation
- Input Validation Framework - Required for 20+ tickets
- Soft-Delete Enforcement (PR003946-66-68) - Data integrity
- Server ID Generation (PR003946-69-70) - Data consistency
- Create test file in appropriate directory
- Use existing fixtures from
conftest.py - Add appropriate pytest markers
- Map test to specific Jira ticket when applicable
- Document expected vs current behavior
- Add new fixtures to
conftest.pyfor reusable test components - Extend validation helpers for new validation patterns
- Update test runner script for new execution modes
- Update documentation with new capabilities
- Tests map to specific Jira requirements
- Both success and failure cases tested
- Error responses validated against schema
- Audit fields validated where applicable
- Test data uses fixtures consistently
- Documentation updated for new features
This testing framework provides a comprehensive foundation for implementing the CMZ API requirements using Test-Driven Development, ensuring all Jira ticket requirements are properly validated and implemented.