Files
orion/docs/testing/index.md

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:

  1. Linting with flake8 and black
  2. Type checking with mypy
  3. Security scanning with bandit
  4. Unit tests on every commit
  5. Integration tests on pull requests
  6. 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

  1. Read the conventions: Test Naming Conventions
  2. Run existing tests: pytest -v
  3. Write your first test: See examples in existing test files
  4. 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