"""Tests for maze solving algorithms.""" import pytest from src.solvers import DFSSolver, BFSSolver from src.generators import RecursiveBacktrackingGenerator SOLVERS = [DFSSolver(), BFSSolver()] class TestSolvers: """Test maze solving algorithms.""" @pytest.mark.parametrize("solver", SOLVERS) def test_solver_finds_solution(self, solver, small_maze): """Test that solver finds a solution.""" result = solver.solve(small_maze) assert result['success'] assert result['path'] is not None assert len(result['path']) > 0 assert result['path_length'] > 0 assert result['time_ms'] >= 0 @pytest.mark.parametrize("solver", SOLVERS) def test_solution_path_validity(self, solver, medium_maze): """Test that solution path is valid.""" result = solver.solve(medium_maze) assert result['success'] path = result['path'] # Path should start at maze start assert path[0] == medium_maze.start # Path should end at maze end assert path[-1] == medium_maze.end # Each step should be adjacent to previous for i in range(len(path) - 1): r1, c1 = path[i] r2, c2 = path[i + 1] # Manhattan distance should be 1 assert abs(r2 - r1) + abs(c2 - c1) == 1 @pytest.mark.parametrize("solver", SOLVERS) def test_solver_visited_cells(self, solver, small_maze): """Test that solver tracks visited cells.""" result = solver.solve(small_maze) assert 'visited' in result assert len(result['visited']) > 0 # Solution path should be subset of visited cells path_set = set(result['path']) visited_set = set(result['visited']) assert path_set.issubset(visited_set) def test_bfs_finds_shortest_path(self): """Test that BFS finds shortest path.""" gen = RecursiveBacktrackingGenerator() maze = gen.generate(10, 10, seed=42) bfs = BFSSolver() dfs = DFSSolver() bfs_result = bfs.solve(maze) dfs_result = dfs.solve(maze) # BFS should find shortest or equal path assert bfs_result['path_length'] <= dfs_result['path_length'] def test_solver_performance(self): """Test solver performance.""" gen = RecursiveBacktrackingGenerator() maze = gen.generate(25, 25, seed=42) for solver in SOLVERS: result = solver.solve(maze) # Should solve 25x25 maze quickly assert result['time_ms'] < 1000 def test_solver_on_different_sizes(self): """Test solvers on different maze sizes.""" gen = RecursiveBacktrackingGenerator() for size in [5, 10, 15, 20]: maze = gen.generate(size, size, seed=42) for solver in SOLVERS: result = solver.solve(maze) assert result['success'] assert result['path_length'] > 0 class TestDFSSolver: """Test DFS-specific functionality.""" def test_dfs_name(self): """Test DFS solver name.""" solver = DFSSolver() assert "DFS" in solver.name or "Depth-First" in solver.name def test_dfs_solves_maze(self, medium_maze): """Test DFS solves maze correctly.""" solver = DFSSolver() result = solver.solve(medium_maze) assert result['success'] assert result['algorithm'] == solver.name class TestBFSSolver: """Test BFS-specific functionality.""" def test_bfs_name(self): """Test BFS solver name.""" solver = BFSSolver() assert "BFS" in solver.name or "Breadth-First" in solver.name def test_bfs_solves_maze(self, medium_maze): """Test BFS solves maze correctly.""" solver = BFSSolver() result = solver.solve(medium_maze) assert result['success'] assert result['algorithm'] == solver.name def test_bfs_optimal_path(self): """Test BFS finds optimal path.""" gen = RecursiveBacktrackingGenerator() # Test on multiple mazes for seed in [42, 100, 200]: maze = gen.generate(15, 15, seed=seed) bfs = BFSSolver() result = bfs.solve(maze) # Verify path exists and is valid assert result['success'] assert result['path_length'] > 0