# 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 ```