"""Tests for maze generation algorithms.""" import pytest from src.generators import ( RecursiveBacktrackingGenerator, KruskalGenerator, PrimGenerator, SidewinderGenerator, HuntAndKillGenerator, EllerGenerator, WilsonGenerator, AldousBroderGenerator ) # All generators to test GENERATORS = [ RecursiveBacktrackingGenerator(), KruskalGenerator(), PrimGenerator(), SidewinderGenerator(), HuntAndKillGenerator(), EllerGenerator(), WilsonGenerator(), AldousBroderGenerator() ] class TestGenerators: """Test all maze generation algorithms.""" @pytest.mark.parametrize("generator", GENERATORS) def test_generator_creates_valid_maze(self, generator): """Test that generator creates a valid maze.""" maze = generator.generate(10, 10, seed=42) assert maze is not None assert maze.rows == 10 assert maze.cols == 10 assert maze.algorithm_used == generator.name assert maze.generation_time_ms >= 0 @pytest.mark.parametrize("generator", GENERATORS) def test_generator_with_different_sizes(self, generator): """Test generator with different maze sizes.""" # Small maze maze_small = generator.generate(5, 5, seed=42) assert maze_small.rows == 5 assert maze_small.cols == 5 # Large maze maze_large = generator.generate(25, 25, seed=42) assert maze_large.rows == 25 assert maze_large.cols == 25 @pytest.mark.parametrize("generator", GENERATORS) def test_generator_reproducibility(self, generator): """Test that same seed produces same maze.""" maze1 = generator.generate(10, 10, seed=42) maze2 = generator.generate(10, 10, seed=42) # Compare wall structures for row in range(10): for col in range(10): cell1 = maze1.get_cell(row, col) cell2 = maze2.get_cell(row, col) assert cell1.walls == cell2.walls @pytest.mark.parametrize("generator", GENERATORS) def test_maze_is_fully_connected(self, generator): """Test that all cells in maze are reachable.""" maze = generator.generate(10, 10, seed=42) # Use BFS to check connectivity start = maze.get_cell(0, 0) visited = set() queue = [start] start.visited = True while queue: current = queue.pop(0) visited.add((current.row, current.col)) neighbors = maze.get_neighbors(current) for neighbor, direction in neighbors: if not neighbor.visited and not current.has_wall(direction): neighbor.visited = True queue.append(neighbor) # All cells should be reachable assert len(visited) == maze.rows * maze.cols @pytest.mark.parametrize("generator", GENERATORS) def test_maze_has_passages(self, generator): """Test that maze has passages (some walls removed).""" maze = generator.generate(10, 10, seed=42) total_walls = 0 for row in maze.grid: for cell in row: total_walls += sum(1 for wall in cell.walls.values() if wall) # Should have fewer walls than a completely walled maze max_walls = 10 * 10 * 4 assert total_walls < max_walls @pytest.mark.parametrize("generator", GENERATORS) def test_generator_performance(self, generator): """Test generator meets performance targets.""" # 10x10 should be very fast maze = generator.generate(10, 10, seed=42) assert maze.generation_time_ms < 1000 # Less than 1 second # Even 25x25 should be reasonable (except Aldous-Broder can be slow) if generator.name != "Aldous-Broder Algorithm": maze = generator.generate(25, 25, seed=42) assert maze.generation_time_ms < 5000 # Less than 5 seconds class TestSpecificGenerators: """Test specific generator properties.""" def test_recursive_backtracking_name(self): """Test recursive backtracking has correct name.""" gen = RecursiveBacktrackingGenerator() assert gen.name == "Recursive Backtracking" def test_kruskal_name(self): """Test Kruskal's has correct name.""" gen = KruskalGenerator() assert gen.name == "Kruskal's Algorithm" def test_prim_name(self): """Test Prim's has correct name.""" gen = PrimGenerator() assert gen.name == "Prim's Algorithm" def test_sidewinder_creates_valid_maze(self): """Test Sidewinder algorithm.""" gen = SidewinderGenerator() maze = gen.generate(10, 10, seed=42) # Top row should have all east walls removed (characteristic of Sidewinder) # Check that top row is mostly connected horizontally top_row = maze.grid[0] east_walls = sum(1 for cell in top_row if cell.has_wall('east')) # Should have mostly removed east walls in top row assert east_walls < len(top_row)