Initial commit
This commit is contained in:
143
tests/unit/test_solvers.py
Normal file
143
tests/unit/test_solvers.py
Normal file
@@ -0,0 +1,143 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user