# Testing Guide - City Builder Game
This document provides comprehensive information about the testing framework for the City Builder multiplayer game.
## Quick Start
### Prerequisites
1. **Start the game server** (required for tests):
```bash
python run.py
```
2. **Run tests** (in another terminal):
```bash
# Install test dependencies
pip install -r requirements.txt
# Run all tests
pytest
# Or use the test runner script
python run_tests.py
```
## Test Structure
### Test Files
- `tests/test_smoke.py` - Basic smoke tests to verify framework
- `tests/test_economy.py` - Economy system and building costs
- `tests/test_multiplayer.py` - Chat, cursor sync, building sync
- `tests/test_game_state.py` - Database persistence and validation
- `tests/test_integration.py` - End-to-end scenarios and stress tests
### Test Utilities
- `tests/test_client.py` - WebSocket client simulator
- `tests/__init__.py` - Test package initialization
- `run_tests.py` - Convenient test runner script
## Test Commands
### Basic Commands
```bash
# Run all tests
pytest
# Run with verbose output
pytest -v
# Run specific test file
pytest tests/test_economy.py
# Run specific test class
pytest tests/test_economy.py::TestEconomySystem
# Run specific test method
pytest tests/test_economy.py::TestEconomySystem::test_building_costs
# Run tests matching pattern
pytest -k "economy"
pytest -k "multiplayer"
```
### Advanced Commands
```bash
# Run tests with coverage (install pytest-cov first)
pip install pytest-cov
pytest --cov=server --cov-report=html
# Run tests in parallel (install pytest-xdist first)
pip install pytest-xdist
pytest -n auto
# Run only failed tests from last run
pytest --lf
# Run tests and stop on first failure
pytest -x
```
## Test Categories
### 🏗️ Economy System Tests (`test_economy.py`)
**What it tests:**
- Building costs and money deduction
- Income/expense calculations per economic tick
- Road connectivity bonuses (5% per road in network)
- Population and power requirements
- Offline player processing (10% income rate)
**Key test methods:**
- `test_building_costs()` - Validates building price configurations
- `test_road_connectivity_bonus()` - Tests economy bonuses from road networks
- `test_offline_economy_processing()` - Verifies 10% income for offline players
- `test_population_requirements()` - Commercial building population requirements
### 👥 Multiplayer Tests (`test_multiplayer.py`)
**What it tests:**
- Real-time chat message broadcasting
- Cursor movement synchronization
- Building placement synchronization
- Player join/leave notifications
- Building ownership and permissions
**Key test methods:**
- `test_chat_message_broadcasting()` - Chat messages reach all players
- `test_building_placement_synchronization()` - Buildings sync across clients
- `test_building_ownership_permissions()` - Only owners can edit/delete buildings
- `test_rapid_chat_messages()` - Stress test for chat system
### 🏛️ Game State Tests (`test_game_state.py`)
**What it tests:**
- Player creation and management
- Building placement/removal validation
- Database save/load operations
- Road network connectivity algorithms
- Game state persistence across reconnections
**Key test methods:**
- `test_player_creation()` - Player data initialization
- `test_road_network_connectivity()` - Flood-fill algorithm for road zones
- `test_save_and_load_game_state()` - Database persistence
- `test_building_placement_validation()` - Validation rules
### 🎮 Integration Tests (`test_integration.py`)
**What it tests:**
- Complete multiplayer game scenarios
- End-to-end workflows
- System performance under load
- Error handling in complex scenarios
**Key test methods:**
- `test_two_player_city_building_session()` - Full multiplayer game
- `test_collaborative_city_with_chat()` - Players working together
- `test_rapid_building_placement()` - Stress test for building system
- `test_mixed_action_stress_test()` - Multiple action types simultaneously
### 💨 Smoke Tests (`test_smoke.py`)
**What it tests:**
- Basic framework functionality
- WebSocket connection establishment
- Simple building placement
- Basic chat functionality
## Test Client Architecture
### TestWebSocketClient
The `TestWebSocketClient` simulates a real game client:
```python
from tests.test_client import TestWebSocketClient
# Create client
client = TestWebSocketClient("player_nickname")
await client.connect()
# Game actions
await client.place_building("small_house", 5, 5)
await client.send_chat("Hello world!")
await client.send_cursor_move(10, 15)
# Receive server messages
message = await client.receive_message(timeout=2.0)
# Clean up
await client.disconnect()
```
### Context Manager Pattern
For easier test management:
```python
from tests.test_client import test_clients
# Single client
async with test_clients("player1") as [client]:
await client.place_building("road", 0, 0)
# Multiple clients
async with test_clients("alice", "bob", "charlie") as [alice, bob, charlie]:
await alice.send_chat("Let's build together!")
# All clients automatically disconnected at end
```
## Test Data Management
### Database Isolation
- Tests use temporary databases to avoid affecting game data
- Each test gets a fresh database state
- Database fixtures handle setup and teardown automatically
### Test Cleanup
- WebSocket connections are automatically closed
- Temporary files are cleaned up
- No test data persists between runs
## Writing New Tests
### Adding Economy Tests
```python
def test_new_building_feature(self, game_setup):
"""Test a new building feature"""
game_state, economy_engine, player = game_setup
# Test the new feature
result = game_state.place_building("player_id", "new_building", 0, 0)
assert result["success"] == True
# Test economy impact
economy_engine.tick()
# Add assertions...
```
### Adding Multiplayer Tests
```python
@pytest.mark.asyncio
async def test_new_multiplayer_feature(self):
"""Test a new multiplayer feature"""
async with test_clients("player1", "player2") as [p1, p2]:
# Test the interaction
await p1.some_new_action()
# Verify p2 receives update
message = await p2.receive_message(timeout=2.0)
assert message["type"] == "expected_message_type"
```
### Test Patterns
**Async Tests:**
```python
@pytest.mark.asyncio
async def test_async_functionality(self):
# Use async/await for WebSocket interactions
pass
```
**Fixtures:**
```python
@pytest.fixture
def game_setup(self):
# Setup test data
return game_state, economy_engine, player
```
**Timeouts:**
```python
# Always use timeouts for WebSocket operations
message = await client.receive_message(timeout=2.0)
```
## Troubleshooting Tests
### Common Issues
**Server not running:**
```
⚠️ Game server is not running on http://127.0.0.1:9901
```
**Solution:** Start the server with `python run.py`
**WebSocket connection failures:**
- Check if server is running on correct port (9901)
- Ensure no firewall blocking localhost connections
- Try restarting the server
**Test timeouts:**
- Economy tests may be slow due to 10-second ticks
- Increase timeouts for integration tests
- Check server logs for errors
**Database errors:**
- Tests should use isolated temporary databases
- If tests interfere, check fixture cleanup
### Debug Mode
Run tests with more verbose output:
```bash
# Maximum verbosity
pytest -vvv
# Show stdout/stderr
pytest -s
# Drop into debugger on failure
pytest --pdb
```
## Continuous Integration
The test suite is designed to be CI-friendly:
- All tests are deterministic
- No external dependencies except the local server
- Isolated database usage
- Reasonable timeouts
- Clear pass/fail criteria
### CI Setup Example
```yaml
# Example GitHub Actions workflow
- name: Install dependencies
run: pip install -r requirements.txt
- name: Start game server
run: python run.py &
- name: Wait for server
run: sleep 5
- name: Run tests
run: pytest -v
```
## Performance Benchmarks
The test suite includes stress tests that validate:
- **Building placement:** 20+ simultaneous actions
- **Chat messages:** 30+ rapid messages
- **Multiple players:** 4+ concurrent clients
- **Mixed actions:** Building + chat + cursor movement
These benchmarks help ensure the game performs well under realistic load.
## Test Coverage Goals
- **WebSocket API:** 100% coverage of all message types
- **Economy system:** All building types and calculation paths
- **Game state:** All validation rules and edge cases
- **Database:** Save/load operations for all data types
- **Multiplayer:** All synchronization scenarios
Run coverage analysis with:
```bash
pip install pytest-cov
pytest --cov=server --cov-report=html
open htmlcov/index.html # View coverage report
```