7.3 KiB
Testing Overview
Our comprehensive test suite ensures code quality, reliability, and maintainability. This section covers everything you need to know about testing in the Letzshop Import project.
Test Structure
We use a hierarchical test organization based on test types and scope:
tests/
├── conftest.py # Core test configuration and fixtures
├── pytest.ini # Pytest configuration with custom markers
├── fixtures/ # Shared test fixtures by domain
├── unit/ # Fast, isolated component tests
├── integration/ # Multi-component interaction tests
├── performance/ # Performance and load tests
├── system/ # End-to-end system behavior tests
└── test_data/ # Test data files (CSV, JSON, etc.)
Test Types
🔧 Unit Tests
Purpose: Test individual components in isolation
Speed: Very fast (< 1 second each)
Scope: Single function, method, or class
# Run unit tests
pytest -m unit
Examples:
- Data processing utilities
- Model validation
- Service business logic
- Individual API endpoint handlers
🔗 Integration Tests
Purpose: Test component interactions
Speed: Fast to moderate (1-5 seconds each)
Scope: Multiple components working together
# Run integration tests
pytest -m integration
Examples:
- API endpoints with database
- Service layer interactions
- Authentication workflows
- File processing pipelines
🏗️ System Tests
Purpose: Test complete application behavior
Speed: Moderate (5-30 seconds each)
Scope: End-to-end user scenarios
# Run system tests
pytest -m system
Examples:
- Complete user registration flow
- Full CSV import process
- Multi-step workflows
- Error handling across layers
⚡ Performance Tests
Purpose: Validate performance requirements
Speed: Slow (30+ seconds each)
Scope: Load, stress, and performance testing
# Run performance tests
pytest -m performance
Examples:
- API response times
- Database query performance
- Large file processing
- Concurrent user scenarios
Running Tests
Basic Commands
# Run all tests
pytest
# Run with verbose output
pytest -v
# Run specific test type
pytest -m unit
pytest -m integration
pytest -m "unit or integration"
# Run tests in specific directory
pytest tests/unit/
pytest tests/integration/api/
# Run specific test file
pytest tests/unit/services/test_product_service.py
# Run specific test class
pytest tests/unit/services/test_product_service.py::TestProductService
# Run specific test method
pytest tests/unit/services/test_product_service.py::TestProductService::test_create_product_success
Advanced Options
# Run with coverage report
pytest --cov=app --cov-report=html
# Run tests matching pattern
pytest -k "product and not slow"
# Stop on first failure
pytest -x
# Run failed tests from last run
pytest --lf
# Run tests in parallel (if pytest-xdist installed)
pytest -n auto
# Show slowest tests
pytest --durations=10
Test Markers
We use pytest markers to categorize and selectively run tests:
| Marker | Purpose |
|---|---|
@pytest.mark.unit |
Fast, isolated component tests |
@pytest.mark.integration |
Multi-component interaction tests |
@pytest.mark.system |
End-to-end system tests |
@pytest.mark.performance |
Performance and load tests |
@pytest.mark.slow |
Long-running tests |
@pytest.mark.api |
API endpoint tests |
@pytest.mark.database |
Tests requiring database |
@pytest.mark.auth |
Authentication/authorization tests |
Example Usage
@pytest.mark.unit
@pytest.mark.products
class TestProductService:
def test_create_product_success(self):
# Test implementation
pass
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.database
def test_product_creation_endpoint():
# Test implementation
pass
Test Configuration
pytest.ini
Our pytest configuration includes:
- Custom markers for test categorization
- Coverage settings with 80% minimum threshold
- Test discovery patterns and paths
- Output formatting for better readability
conftest.py
Core test fixtures and configuration:
- Database fixtures for test isolation
- Authentication fixtures for user/admin testing
- Client fixtures for API testing
- Mock fixtures for external dependencies
Test Data Management
Fixtures
We organize fixtures by domain:
# tests/fixtures/product_fixtures.py
@pytest.fixture
def sample_product():
return {
"name": "Test Product",
"gtin": "1234567890123",
"price": "19.99"
}
@pytest.fixture
def product_factory():
def _create_product(**kwargs):
defaults = {"name": "Test", "gtin": "1234567890123"}
defaults.update(kwargs)
return defaults
return _create_product
Test Data Files
Static test data in tests/test_data/:
- CSV files for import testing
- JSON files for API testing
- Sample configuration files
Coverage Requirements
We maintain high test coverage standards:
- Minimum coverage: 80% overall
- Critical paths: 95%+ coverage required
- New code: Must include tests
- HTML reports: Generated in
htmlcov/
# Generate coverage report
pytest --cov=app --cov-report=html --cov-report=term-missing
Best Practices
Test Naming
- Use descriptive test names that explain the scenario
- Follow the pattern:
test_{action}_{scenario}_{expected_outcome} - See our Test Naming Conventions for details
Test Structure
- Arrange: Set up test data and conditions
- Act: Execute the code being tested
- Assert: Verify the expected outcome
def test_create_product_with_valid_data_returns_product(self):
# Arrange
product_data = {"name": "Test", "gtin": "1234567890123"}
# Act
result = product_service.create_product(product_data)
# Assert
assert result is not None
assert result.name == "Test"
Test Isolation
- Each test should be independent
- Use database transactions that rollback
- Mock external dependencies
- Clean up test data
Continuous Integration
Our CI pipeline runs:
- Linting with flake8 and black
- Type checking with mypy
- Security scanning with bandit
- Unit tests on every commit
- Integration tests on pull requests
- Performance tests on releases
Tools and Libraries
- pytest: Test framework and runner
- pytest-cov: Coverage reporting
- pytest-asyncio: Async test support
- pytest-mock: Mocking utilities
- faker: Test data generation
- httpx: HTTP client for API testing
- factory-boy: Test object factories
Getting Started
- Read the conventions: Test Naming Conventions
- Run existing tests:
pytest -v - Write your first test: See examples in existing test files
- Check coverage:
pytest --cov
Need Help?
- Examples: Look at existing tests in
tests/directory - Documentation: This testing section has detailed guides
- Issues: Create a GitHub issue for testing questions
- Standards: Follow our naming conventions