299 lines
7.3 KiB
Markdown
299 lines
7.3 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# Run performance tests
|
|
pytest -m performance
|
|
```
|
|
|
|
**Examples**:
|
|
- API response times
|
|
- Database query performance
|
|
- Large file processing
|
|
- Concurrent user scenarios
|
|
|
|
## Running Tests
|
|
|
|
### Basic Commands
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```python
|
|
@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:
|
|
|
|
```python
|
|
# 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/`
|
|
|
|
```bash
|
|
# 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](test-naming-conventions.md) for details
|
|
|
|
### Test Structure
|
|
- **Arrange**: Set up test data and conditions
|
|
- **Act**: Execute the code being tested
|
|
- **Assert**: Verify the expected outcome
|
|
|
|
```python
|
|
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](test-naming-conventions.md)
|
|
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](test-naming-conventions.md) |