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