Testing Guide
Comprehensive guidelines for writing and running tests in the Zyeta backend
This guide outlines the testing strategy, standards, and best practices for the Zyeta backend codebase. It serves as a blueprint for developers to ensure consistent quality and reliability through automated testing.
Overview
A robust testing approach is crucial for maintaining code quality and ensuring that our services function correctly after changes. Our testing strategy comprises multiple levels:
Test Pyramid
The test pyramid represents the ideal distribution of different test types:
This visualization demonstrates that:
- Unit tests should form the majority of your test suite (fastest to run, easiest to write)
- Integration tests should be fewer in number but cover critical component interactions
- End-to-End tests should be the fewest but test complete user workflows
Test Directory Structure
Organize tests with a clear structure that mirrors the source code:
Setting Up the Testing Environment
Prerequisites
The project uses pytest for running tests. Dependencies are managed through Poetry and include:
- pytest
- pytest-asyncio (for testing async code)
- pytest-cov (for coverage reporting)
These are already included in pyproject.toml
.
Test Configuration
Create a conftest.py
file at the root of the tests directory to define shared fixtures:
Test Fixture Dependencies
Unit Tests
Unit tests focus on testing individual components in isolation.
Writing Unit Tests for Models
Unit Test Flow
Writing Unit Tests for Services
Integration Tests
Integration tests verify that different components work together correctly.
Testing Service Integration
Integration Test Service Interaction
Testing Database Operations
CRUD Operations Sequence
End-to-End (E2E) Tests
E2E tests verify that the entire system works as expected.
Testing API Endpoints
E2E Test Flow
Mocking
Proper use of mocks is essential for isolation and controlled testing.
Mocking External Services
Mocking Concept Visualization
Test Fixtures
Create reusable fixtures to reduce code duplication and simplify tests.
Model Fixtures
Test Coverage
Aim for high test coverage of the codebase.
Running Coverage Reports
Coverage Targets
- Unit Tests: Aim for 80%+ coverage of all functions and methods
- Integration Tests: Cover all major service interactions
- E2E Tests: Cover all API endpoints and primary user flows
Continuous Integration
Tests will be integrated into the CI/CD pipeline to ensure code quality.
CI/CD Workflow
GitHub Actions Configuration
Update the .github/workflows/pre-commit.yml
file to include testing:
Testing Strategies by Component
Models
- Test model instantiation
- Test relationships between models
- Test constraints and defaults
Services
- Test business logic
- Test error handling
- Test edge cases
- Mock external dependencies
API Endpoints
- Test request validation
- Test authentication/authorization
- Test response format
- Test error responses
Component Testing Focus
Best Practices
General Guidelines
- Test pyramid: Write more unit tests than integration tests, and more integration tests than E2E tests
- Test isolation: Each test should be independent and not rely on the state from other tests
- Descriptive naming: Use clear, descriptive names for test functions
- Arrange-Act-Assert: Structure tests with clear sections for setup, execution, and verification
- Don’t test implementation details: Focus on behavior, not implementation
Test Organization Pattern
Asynchronous Testing
Since our application uses async/await, follow these practices:
- Use
pytest.mark.asyncio
decorator for async test functions - Use
async
fixtures where needed - Handle event loops properly
Testing Database Operations
- Use transactions to isolate tests
- Roll back after each test
- Use a separate test database
Common Pitfalls
- Slow tests: Keep tests fast, especially unit tests
- Flaky tests: Avoid tests that sometimes pass and sometimes fail
- Over-mocking: Don’t mock everything; test real interactions where practical
- Hardcoded test data: Use fixtures and factories for test data
- Missing edge cases: Test error paths, not just happy paths
Testing Pitfalls and Solutions
Conclusion
A comprehensive testing strategy is essential for maintaining a healthy codebase. By following this guide, developers can write effective tests that ensure the reliability and quality of the Zyeta backend.
Remember that tests are an investment in the future of the codebase, making it safer to refactor and extend functionality while maintaining confidence in the system’s behavior.
Additional Resources
Was this page helpful?