mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-07-04 20:03:12 +02:00
- Add comprehensive tests for all packages (3572 tests, 100% branch coverage) - Split oversized test files to stay under 500-line limit - Add per-file ruff ignores for test-appropriate suppressions - Fix _cache_decks.py to properly convert JSON lists to tuples - Add session-scoped conftest fixture for logging handler cleanup (Python 3.14) - Update ruff pre-commit hook to v0.15.2 - Add codespell ignore words for test data - Add generated output files to .gitignore
93 lines
3.1 KiB
Python
93 lines
3.1 KiB
Python
"""Tests for uncovered branches in python_pkg.puzzle_solver.solver."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
from python_pkg.puzzle_solver.solver import (
|
|
Puzzle,
|
|
print_solution,
|
|
)
|
|
|
|
if TYPE_CHECKING:
|
|
import pytest
|
|
|
|
|
|
def _make_puzzle(squares_data: list[dict[str, Any]]) -> Puzzle:
|
|
return Puzzle.from_json({"squares": squares_data})
|
|
|
|
|
|
# ── print_solution ───────────────────────────────────────────────────
|
|
|
|
|
|
class TestPrintSolution:
|
|
def test_prints_valid_moves(self, capsys: pytest.CaptureFixture[str]) -> None:
|
|
"""Successfully prints all solution steps."""
|
|
p = _make_puzzle(
|
|
[
|
|
{"pos": [0, 0], "type": "player"},
|
|
{"pos": [0, 1], "type": "normal"},
|
|
{"pos": [0, 2], "type": "goal"},
|
|
]
|
|
)
|
|
print_solution(p, ["right"])
|
|
|
|
def test_stops_on_none_result(self) -> None:
|
|
"""Returns early when _simulate_move returns None."""
|
|
p = _make_puzzle(
|
|
[
|
|
{"pos": [0, 0], "type": "player"},
|
|
{"pos": [0, 1], "type": "goal"},
|
|
]
|
|
)
|
|
# "up" from (0,0) goes off-grid → _simulate_move returns None → early return
|
|
print_solution(p, ["up", "right"])
|
|
|
|
def test_multiple_moves(self, capsys: pytest.CaptureFixture[str]) -> None:
|
|
"""Prints multiple steps in sequence."""
|
|
p = _make_puzzle(
|
|
[
|
|
{"pos": [0, 0], "type": "player"},
|
|
{"pos": [0, 1], "type": "normal"},
|
|
{"pos": [0, 2], "type": "normal"},
|
|
{"pos": [0, 3], "type": "goal"},
|
|
{"pos": [1, 0], "type": "normal"},
|
|
]
|
|
)
|
|
# right lands on (0,1), right again lands on (0,2), right again → goal
|
|
print_solution(p, ["right", "right", "right"])
|
|
|
|
def test_with_locks(self) -> None:
|
|
"""Handles state with initial locks correctly."""
|
|
p = _make_puzzle(
|
|
[
|
|
{"pos": [0, 0], "type": "player"},
|
|
{"pos": [0, 1], "type": "key", "lock_id": 1},
|
|
{"pos": [1, 0], "type": "lock", "lock_id": 1},
|
|
{"pos": [0, 2], "type": "goal"},
|
|
]
|
|
)
|
|
print_solution(p, ["right", "right"])
|
|
|
|
def test_empty_moves_list(self) -> None:
|
|
"""No moves → prints nothing."""
|
|
p = _make_puzzle(
|
|
[
|
|
{"pos": [0, 0], "type": "player"},
|
|
{"pos": [0, 1], "type": "goal"},
|
|
]
|
|
)
|
|
print_solution(p, [])
|
|
|
|
def test_with_teleporter(self) -> None:
|
|
"""Teleporter warping is tracked in state."""
|
|
p = _make_puzzle(
|
|
[
|
|
{"pos": [0, 0], "type": "player"},
|
|
{"pos": [0, 1], "type": "teleporter", "group": 1},
|
|
{"pos": [2, 0], "type": "teleporter", "group": 1},
|
|
{"pos": [2, 1], "type": "goal"},
|
|
]
|
|
)
|
|
print_solution(p, ["right", "right"])
|