Initial commit

This commit is contained in:
2025-11-20 22:58:11 -05:00
commit 6d75c8e94e
51 changed files with 5141 additions and 0 deletions

143
tests/unit/test_solvers.py Normal file
View 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