12 KiB
Test Naming Conventions
This document outlines the naming conventions used in our test suite to ensure consistency, clarity, and maintainability across the project.
Overview
Our test suite follows a hierarchical structure organized by test type and component, with clear naming patterns that make it easy to locate and understand test purposes.
Directory Structure
tests/
├── conftest.py # Core test configuration and fixtures
├── pytest.ini # Pytest configuration
├── fixtures/ # Shared test fixtures organized 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.)
File Naming Conventions
General Rule
All test files must start with test_ prefix for pytest auto-discovery.
Pattern: test_{component/feature}.py
Unit Tests (tests/unit/)
Focus on testing individual components in isolation.
tests/unit/
├── models/
│ ├── test_database_models.py # Database model tests
│ ├── test_api_models.py # API model validation
│ └── test_model_relationships.py # Model relationship tests
├── utils/
│ ├── test_data_processing.py # Data processing utilities
│ ├── test_csv_processor.py # CSV processing utilities
│ ├── test_validators.py # Validation utilities
│ └── test_formatters.py # Data formatting utilities
├── services/
│ ├── test_admin_service.py # Admin service business logic
│ ├── test_auth_service.py # Authentication service
│ ├── test_product_service.py # Product management service
│ ├── test_shop_service.py # Shop management service
│ ├── test_stock_service.py # Stock management service
│ ├── test_marketplace_service.py # Marketplace import service
│ └── test_stats_service.py # Statistics service
└── core/
├── test_config.py # Configuration management
├── test_database.py # Database utilities
└── test_logging.py # Logging functionality
Integration Tests (tests/integration/)
Focus on testing interactions between multiple components.
tests/integration/
├── api/v1/
│ ├── test_auth_endpoints.py # Authentication API endpoints
│ ├── test_admin_endpoints.py # Admin API endpoints
│ ├── test_product_endpoints.py # Product CRUD endpoints
│ ├── test_shop_endpoints.py # Shop management endpoints
│ ├── test_stock_endpoints.py # Stock management endpoints
│ ├── test_marketplace_endpoints.py # Import endpoints
│ ├── test_stats_endpoints.py # Statistics endpoints
│ └── test_pagination.py # Pagination functionality
├── database/
│ ├── test_migrations.py # Database migration tests
│ ├── test_transactions.py # Transaction handling
│ └── test_constraints.py # Database constraints
├── security/
│ ├── test_authentication.py # Authentication mechanisms
│ ├── test_authorization.py # Permission and role tests
│ ├── test_input_validation.py # Input security validation
│ ├── test_rate_limiting.py # Rate limiting middleware
│ └── test_cors.py # CORS configuration
└── workflows/
├── test_product_import_workflow.py # Complete import process
├── test_user_registration_flow.py # User registration process
└── test_shop_setup_flow.py # Shop creation workflow
System Tests (tests/system/)
Focus on end-to-end application behavior.
tests/system/
├── test_application_startup.py # Application initialization
├── test_error_handling.py # Global error handling
├── test_health_checks.py # Health endpoint tests
├── test_database_connectivity.py # Database connection tests
└── test_external_dependencies.py # Third-party service tests
Performance Tests (tests/performance/)
Focus on performance benchmarks and load testing.
tests/performance/
├── test_api_performance.py # API endpoint performance
├── test_database_performance.py # Database query performance
├── test_import_performance.py # Large file import tests
└── test_concurrent_users.py # Multi-user scenarios
Class Naming Conventions
Use descriptive class names that clearly indicate what is being tested:
Pattern: Test{ComponentName}{TestType}
# Good examples
class TestProductService: # Testing ProductService class
class TestProductModel: # Testing Product model
class TestProductEndpoints: # Testing product API endpoints
class TestProductValidation: # Testing product validation logic
class TestProductPermissions: # Testing product access control
# Avoid generic names
class TestProduct: # Too vague - what aspect of Product?
class Tests: # Too generic
Specialized Class Naming
class TestProductCRUD: # CRUD operations
class TestProductSecurity: # Security-related tests
class TestProductErrorHandling: # Error scenario tests
class TestProductEdgeCases: # Boundary condition tests
Method Naming Conventions
Test method names should be descriptive and follow a clear pattern that explains:
- What is being tested
- The scenario/condition
- Expected outcome
Pattern: test_{action}_{scenario}_{expected_outcome}
# Good examples - Clear and descriptive
def test_create_product_with_valid_data_returns_product():
def test_create_product_with_invalid_gtin_raises_validation_error():
def test_get_product_by_id_when_not_found_returns_404():
def test_update_product_without_permission_raises_forbidden():
def test_delete_product_with_existing_stock_prevents_deletion():
# Acceptable shorter versions
def test_create_product_success():
def test_create_product_invalid_data():
def test_create_product_unauthorized():
def test_get_product_not_found():
Method Naming Patterns by Scenario
Happy Path Tests:
def test_create_user_success():
def test_login_valid_credentials():
def test_import_csv_valid_format():
Error/Edge Case Tests:
def test_create_user_duplicate_email_fails():
def test_login_invalid_credentials_rejected():
def test_import_csv_malformed_data_raises_error():
Permission/Security Tests:
def test_admin_endpoint_requires_admin_role():
def test_user_cannot_access_other_user_data():
def test_api_key_required_for_marketplace_import():
Boundary/Edge Cases:
def test_pagination_with_zero_items():
def test_price_with_maximum_decimal_places():
def test_gtin_with_minimum_valid_length():
Marker Usage
Use pytest markers to categorize and run specific test types:
@pytest.mark.unit
class TestProductService:
"""Unit tests for ProductService business logic"""
@pytest.mark.integration
@pytest.mark.api
class TestProductEndpoints:
"""Integration tests for Product API endpoints"""
@pytest.mark.slow
@pytest.mark.performance
class TestImportPerformance:
"""Performance tests for large CSV imports"""
Available Markers
| 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 |
@pytest.mark.admin |
Admin functionality tests |
File Organization Best Practices
Mirror Source Structure
Test files should mirror the source code structure:
app/services/product_service.py → tests/unit/services/test_product_service.py
app/api/v1/admin.py → tests/integration/api/v1/test_admin_endpoints.py
Group Related Tests
Keep related tests in the same file:
# test_product_service.py
class TestProductCreation: # All product creation scenarios
class TestProductValidation: # All validation scenarios
class TestProductQueries: # All query scenarios
Separate Complex Workflows
Break complex workflows into separate files:
test_user_registration_flow.py # Complete registration process
test_shop_setup_flow.py # Shop creation workflow
test_product_import_workflow.py # CSV import end-to-end
Running Tests by Name Pattern
Use pytest's flexible test discovery:
# Run all unit tests
pytest tests/unit/ -v
# Run specific component tests
pytest tests/ -k "product" -v
# Run by marker
pytest -m "unit and not slow" -v
# Run specific test class
pytest tests/unit/services/test_product_service.py::TestProductService -v
# Run specific test method
pytest tests/unit/services/test_product_service.py::TestProductService::test_create_product_success -v
Examples
Complete Test File Example
# tests/unit/services/test_product_service.py
import pytest
from unittest.mock import Mock, patch
from app.services.product_service import ProductService
from app.models.database_models import Product
@pytest.mark.unit
class TestProductService:
"""Unit tests for ProductService business logic"""
def setup_method(self):
"""Setup run before each test method"""
self.service = ProductService()
self.mock_db = Mock()
def test_create_product_with_valid_data_returns_product(self):
"""Test successful product creation with valid input data"""
# Arrange
product_data = {
"name": "Test Product",
"gtin": "1234567890123",
"price": "19.99"
}
# Act
result = self.service.create_product(product_data)
# Assert
assert result is not None
assert result.name == "Test Product"
def test_create_product_with_invalid_gtin_raises_validation_error(self):
"""Test product creation fails with invalid GTIN format"""
# Arrange
product_data = {
"name": "Test Product",
"gtin": "invalid_gtin",
"price": "19.99"
}
# Act & Assert
with pytest.raises(ValidationError, match="Invalid GTIN format"):
self.service.create_product(product_data)
@pytest.mark.unit
class TestProductValidation:
"""Unit tests for product validation logic"""
def test_validate_gtin_with_valid_format_returns_true(self):
"""Test GTIN validation accepts valid 13-digit GTIN"""
assert ProductService.validate_gtin("1234567890123") is True
def test_validate_gtin_with_invalid_format_returns_false(self):
"""Test GTIN validation rejects invalid format"""
assert ProductService.validate_gtin("invalid") is False
Naming Anti-Patterns to Avoid
❌ Avoid these patterns:
# Too generic
def test_product():
def test_user():
def test_api():
# Unclear purpose
def test_function():
def test_method():
def test_endpoint():
# Non-descriptive
def test_1():
def test_a():
def test_scenario():
# Inconsistent naming
def testProductCreation(): # Wrong case
def test_product_creation(): # Good
def TestProductCreation(): # Wrong - this is for classes
✅ Use these patterns instead:
# Clear, descriptive, consistent
def test_create_product_with_valid_data_succeeds():
def test_authenticate_user_with_invalid_token_fails():
def test_get_products_endpoint_returns_paginated_results():
Following these naming conventions will help maintain a clean, understandable, and maintainable test suite that scales with your project.