Add comprehensive test suite for game mechanics and level handling
- Introduced `test_final_level_flow.py` to validate final level transitions and game end scenarios. - Created `test_game_over_flow.py` to ensure game over conditions trigger correctly based on rat counts. - Implemented `test_keybindings.py` to verify keybinding configurations and their context-specific actions. - Developed `test_level_editor.py` to assess level editor functionalities and layout computations. - Added `test_level_io.py` for testing level data serialization and deserialization. - Established `test_loop_logic_parity.py` to ensure consistent game state across multiple simulation runs. - Created `test_non_regression.py` to simulate game behavior and capture states for future verification. - Implemented `test_verify.py` to compare current game states against a golden master for regression detection.
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import random
|
||||
from pathlib import Path
|
||||
|
||||
# Add current directory to path
|
||||
sys.path.append(os.getcwd())
|
||||
|
||||
# Set SDL to use dummy video driver for headless environments
|
||||
os.environ["SDL_VIDEODRIVER"] = "dummy"
|
||||
os.environ["SDL_AUDIODRIVER"] = "dummy"
|
||||
os.environ["MICE_DISABLE_JOYSTICK"] = "1"
|
||||
|
||||
from rats import MiceMaze
|
||||
from engine.state_machine import GameState
|
||||
from engine.sdl2 import GameWindow
|
||||
|
||||
def mock_init_audio(self):
|
||||
self.music_enabled = False
|
||||
self.audio_devs = {"base": 0, "effects": 0, "music": 0}
|
||||
self.sound_volume = 0
|
||||
self.music_volume = 0
|
||||
|
||||
class TestGameOverFlow(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
GameWindow.show_intro = lambda *args, **kwargs: None
|
||||
GameWindow.show_loading_screen = lambda *args, **kwargs: None
|
||||
GameWindow._init_audio_system = mock_init_audio
|
||||
GameWindow.play_sound = lambda *args, **kwargs: None
|
||||
GameWindow.stop_sound = lambda *args, **kwargs: None
|
||||
|
||||
def setUp(self):
|
||||
random.seed(42)
|
||||
# Load a standard level
|
||||
self.game = MiceMaze("assets/Rat/level.dat", level_index=0)
|
||||
self.game.game_status = "game"
|
||||
self.game.state_machine.transition_to(GameState.PLAYING)
|
||||
|
||||
def test_defeat_triggers_game_over_state(self):
|
||||
"""Verify that having > 200 rats triggers GAME_OVER state, not PAUSED."""
|
||||
print("\nTesting defeat condition (> 200 rats)...")
|
||||
|
||||
# Manually inject > 200 rats to trigger defeat
|
||||
from units.rat import Male
|
||||
for i in range(210):
|
||||
self.game.unit_manager.spawn_unit(Male, (1, 1))
|
||||
|
||||
# Run one update cycle
|
||||
self.game.update_maze()
|
||||
|
||||
# Check end condition
|
||||
self.assertTrue(self.game.game_end[0], "Game should be marked as ended")
|
||||
self.assertEqual(self.game.game_end[1], "defeat", "End reason should be defeat")
|
||||
|
||||
# CRITICAL CHECK: State must be GAME_OVER, not PAUSED
|
||||
current_state = self.game.state_machine.current_state
|
||||
print(f"Current State: {current_state}")
|
||||
print(f"Legacy game_status: {self.game.game_status}")
|
||||
|
||||
self.assertEqual(current_state, GameState.GAME_OVER,
|
||||
f"Game should be in GAME_OVER state, but was in {current_state}")
|
||||
|
||||
def test_victory_triggers_victory_state(self):
|
||||
"""Verify that clearing all rats triggers VICTORY state."""
|
||||
print("\nTesting victory condition (0 rats)...")
|
||||
|
||||
# Clear all units
|
||||
self.game.units.clear()
|
||||
|
||||
# Run one update cycle
|
||||
self.game.update_maze()
|
||||
|
||||
# Check end condition
|
||||
self.assertTrue(self.game.game_end[0], "Game should be marked as ended")
|
||||
self.assertEqual(self.game.game_end[1], "level_clear", "End reason should be level_clear")
|
||||
|
||||
# State must be VICTORY
|
||||
current_state = self.game.state_machine.current_state
|
||||
print(f"Current State: {current_state}")
|
||||
|
||||
self.assertEqual(current_state, GameState.VICTORY,
|
||||
f"Game should be in VICTORY state, but was in {current_state}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user