Establishes foundation for migrating baseball simulation from Discord bot to web application using service-oriented architecture pattern. Key components: - FastAPI application structure with dependency injection - Service layer foundation with base classes and container - Comprehensive directory documentation with README files - PostgreSQL containerization with Docker Compose - Testing structure for unit/integration/e2e tests - Migration planning documentation - Rotating log configuration per user requirements Architecture follows Model/Service/Controller pattern to improve testability, maintainability, and scalability over original monolithic Discord app. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
5.3 KiB
5.3 KiB
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
- Services: Core business logic with mocked dependencies
- Engine: Stateless game simulation functions
- Integration: Service interactions with real database
- 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:
# 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:
# 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:
# 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):
# 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:
# 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
pytest
Specific Test Types
# 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
# 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:
# 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_URLenvironment 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:
- Extract and test business logic in service unit tests
- Validate game mechanics with engine tests
- Test service integration with database
- Ensure web interface works with e2e tests