|
"""
|
|
Pytest configuration and fixtures for the City Builder test suite.
|
|
This provides clean test isolation by resetting the server state before each test.
|
|
"""
|
|
import pytest
|
|
import asyncio
|
|
import tempfile
|
|
import os
|
|
import time
|
|
from pathlib import Path
|
|
|
|
# Import server components
|
|
from server.main import initialize_components, game_state, ws_manager, economy_engine, database
|
|
from server.game_state import GameState
|
|
from server.economy import EconomyEngine
|
|
from server.database import Database
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
|
async def fresh_server_state():
|
|
"""
|
|
Fixture that provides fresh server state for each test.
|
|
This resets the global server components with a clean test database.
|
|
"""
|
|
# Create temporary database for this test
|
|
temp_fd, temp_db_path = tempfile.mkstemp(suffix=".db")
|
|
os.close(temp_fd)
|
|
|
|
try:
|
|
# Initialize server components with test database
|
|
test_game_state, test_ws_manager, test_economy_engine, test_database = initialize_components(temp_db_path)
|
|
|
|
# Initialize the test database
|
|
test_database.init_db()
|
|
|
|
# Yield the components for the test
|
|
yield {
|
|
'game_state': test_game_state,
|
|
'ws_manager': test_ws_manager,
|
|
'economy_engine': test_economy_engine,
|
|
'database': test_database,
|
|
'db_path': temp_db_path
|
|
}
|
|
|
|
finally:
|
|
# Clean up temporary database
|
|
if os.path.exists(temp_db_path):
|
|
os.unlink(temp_db_path)
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
|
def isolated_game_components():
|
|
"""
|
|
Fixture providing completely isolated game components for unit tests.
|
|
These are separate from the server's global state.
|
|
"""
|
|
# Create temporary database for this test
|
|
temp_fd, temp_db_path = tempfile.mkstemp(suffix=".db")
|
|
os.close(temp_fd)
|
|
|
|
try:
|
|
# Create fresh, isolated components
|
|
game_state = GameState()
|
|
economy_engine = EconomyEngine(game_state)
|
|
database = Database(temp_db_path)
|
|
database.init_db()
|
|
|
|
yield game_state, economy_engine, database
|
|
|
|
finally:
|
|
# Clean up temporary database
|
|
if os.path.exists(temp_db_path):
|
|
os.unlink(temp_db_path)
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
|
def unique_coordinates():
|
|
"""
|
|
Fixture that provides unique coordinates for each test to avoid conflicts.
|
|
Uses timestamp-based coordinates to ensure uniqueness.
|
|
"""
|
|
base_time = int(time.time() * 1000) % 10000 # Get last 4 digits of timestamp
|
|
|
|
def get_coords(offset=0):
|
|
"""Get unique coordinates with optional offset"""
|
|
x = (base_time + offset) % 100
|
|
y = (base_time + offset * 2) % 100
|
|
return x, y
|
|
|
|
return get_coords
|
|
|
|
|
|
# Configure asyncio mode for all tests
|
|
pytest_plugins = ('pytest_asyncio',) |