# 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}` ```python # 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 ```python 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: 1. What is being tested 2. The scenario/condition 3. Expected outcome ### Pattern: `test_{action}_{scenario}_{expected_outcome}` ```python # 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:** ```python def test_create_user_success(): def test_login_valid_credentials(): def test_import_csv_valid_format(): ``` **Error/Edge Case Tests:** ```python def test_create_user_duplicate_email_fails(): def test_login_invalid_credentials_rejected(): def test_import_csv_malformed_data_raises_error(): ``` **Permission/Security Tests:** ```python 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:** ```python 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: ```python @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: ```python # 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: ```bash # 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 ```python # 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:** ```python # 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:** ```python # 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.