# Tests Directory This directory contains the comprehensive test suite for the Paper Dynasty web app, organized by testing scope and purpose following the Model/Service Architecture. ## Testing Strategy ### Test Pyramid Structure - **Unit Tests (80%+ coverage)**: Fast, isolated tests for services and engine - **Integration Tests (70%+ coverage)**: Service + database interactions - **End-to-End Tests (Happy path)**: Complete user workflows ### Testing Priorities 1. **Services**: Core business logic with mocked dependencies 2. **Engine**: Stateless game simulation functions 3. **Integration**: Service interactions with real database 4. **Routes**: HTTP handling with mocked services ## Directory Structure ``` tests/ ├── unit/ # Fast, isolated unit tests │ ├── services/ # Service unit tests (MOST IMPORTANT) │ ├── engine/ # Engine unit tests │ └── models/ # Model validation tests ├── integration/ # Service + database integration └── e2e/ # Full application tests ``` ## Unit Tests (`unit/`) ### Services (`unit/services/`) **Critical for Model/Service Architecture** Tests business logic independently of database and web framework: ```python # test_game_service.py @pytest.fixture def mock_session(): return Mock(spec=Session) @pytest.fixture def game_service(mock_session): return GameService(mock_session) @pytest.mark.asyncio async def test_create_game_validates_teams(game_service): # Test business logic without database with pytest.raises(ValidationError): await game_service.create_game(999, 1000) # Invalid teams ``` ### Engine (`unit/engine/`) Tests stateless game simulation functions: ```python # test_dice.py def test_dice_probability_distribution(): # Test dice rolling mechanics results = [roll_dice() for _ in range(1000)] assert 1 <= min(results) <= max(results) <= 6 # test_simulation.py def test_pitcher_vs_batter_mechanics(): # Test core game simulation result = simulate_at_bat(pitcher_stats, batter_stats) assert result.outcome in ['hit', 'out', 'walk', 'strikeout'] ``` ### Models (`unit/models/`) Tests data validation and relationships: ```python # test_models.py def test_game_model_validation(): # Test SQLModel validation with pytest.raises(ValidationError): Game(away_team_id=None) # Required field ``` ## Integration Tests (`integration/`) Tests service interactions with real database (isolated transactions): ```python # test_game_flow.py @pytest.mark.asyncio async def test_complete_game_creation_flow(db_session): game_service = GameService(db_session) # Create test data team1 = await create_test_team(db_session) team2 = await create_test_team(db_session) # Test full flow with real database game = await game_service.create_game(team1.id, team2.id) assert game.id is not None assert game.away_team_id == team1.id ``` ## End-to-End Tests (`e2e/`) Tests complete user journeys through web interface: ```python # test_game_creation.py def test_user_can_create_game(client): # Test complete user workflow response = client.post("/auth/login") # Login response = client.post("/games/start", json={...}) # Create game response = client.get(f"/game/{game_id}") # View game assert "Game created successfully" in response.text ``` ## Running Tests ### All Tests ```bash pytest ``` ### Specific Test Types ```bash # Unit tests only (fast) pytest tests/unit/ # Integration tests only pytest tests/integration/ # End-to-end tests only pytest tests/e2e/ # Specific service tests pytest tests/unit/services/test_game_service.py # Single test function pytest tests/unit/services/test_game_service.py::test_create_game_success ``` ### With Coverage ```bash # Coverage report pytest --cov=app # Coverage with HTML report pytest --cov=app --cov-report=html ``` ## Test Configuration ### Fixtures Common test fixtures for database, services, and test data: ```python # conftest.py @pytest.fixture def db_session(): # Isolated database session for integration tests pass @pytest.fixture def mock_game_service(): # Mocked service for route testing pass @pytest.fixture def test_game_data(): # Sample game data for tests pass ``` ### Test Database Integration tests use a separate test database: - `DATABASE_TEST_URL` environment variable - Isolated transactions (rollback after each test) - Clean state for each test ## Testing Best Practices ### Service Testing - **Mock database sessions** for unit tests - **Test business logic** independently of framework - **Validate error handling** and edge cases - **Test service interactions** with integration tests ### Test Data Management - **Use factories** for creating test data - **Isolate test state** (no shared mutable state) - **Clean up after tests** (database rollback) ### Coverage Goals - **Services**: 90%+ coverage (core business logic) - **Engine**: 95%+ coverage (critical game mechanics) - **Routes**: 80%+ coverage (HTTP handling) - **Models**: 85%+ coverage (data validation) ## Migration Testing When migrating from Discord app: 1. **Extract and test business logic** in service unit tests 2. **Validate game mechanics** with engine tests 3. **Test service integration** with database 4. **Ensure web interface** works with e2e tests