Add game core logic, CSV storage, tests and ADR-0001 (MIL-002)

Task: MIL-002#1
Task: MIL-002#2
Task: MIL-002#3
Task: MIL-002#4
Task: MIL-002#5
This commit is contained in:
2026-10-13 15:48:08 +08:00
parent 048a6ba91d
commit bb8730c307
8 changed files with 363 additions and 2 deletions
+41
View File
@@ -0,0 +1,41 @@
"""Tests of the pure game logic in states.py."""
from us_states_game.states import State, find_state, get_missing_states
STATES = [State("Alabama", 139, -77), State("Ohio", 100, 20), State("Texas", -50, -120)]
def test_find_state_matches_exact_name() -> None:
assert find_state("Ohio", STATES) == State("Ohio", 100, 20)
def test_find_state_ignores_case() -> None:
assert find_state("oHiO", STATES) == State("Ohio", 100, 20)
def test_find_state_ignores_surrounding_whitespace() -> None:
assert find_state(" ohio \n", STATES) == State("Ohio", 100, 20)
def test_find_state_returns_none_for_unknown_answer() -> None:
assert find_state("Atlantis", STATES) is None
def test_find_state_returns_none_for_empty_answer() -> None:
assert find_state("", STATES) is None
def test_find_state_returns_none_for_blank_answer() -> None:
assert find_state(" ", STATES) is None
def test_get_missing_states_keeps_order_of_states() -> None:
assert get_missing_states(STATES, ["Ohio"]) == ["Alabama", "Texas"]
def test_get_missing_states_is_empty_when_all_guessed() -> None:
assert get_missing_states(STATES, ["Texas", "Ohio", "Alabama"]) == []
def test_get_missing_states_returns_all_when_none_guessed() -> None:
assert get_missing_states(STATES, []) == ["Alabama", "Ohio", "Texas"]
+50
View File
@@ -0,0 +1,50 @@
"""Tests of the CSV input and output in storage.py."""
import csv
from pathlib import Path
from us_states_game.constants import NUMBER_OF_STATES, STATE_COLUMN
from us_states_game.states import State, get_missing_states
from us_states_game.storage import load_states, save_states_to_learn
def _read_rows(path: Path) -> list[list[str]]:
with path.open(newline="", encoding="utf-8") as file:
return list(csv.reader(file))
def test_load_states_returns_all_states() -> None:
assert len(load_states()) == NUMBER_OF_STATES
def test_load_states_reads_alabama_coordinates() -> None:
assert load_states()[0] == State("Alabama", 139, -77)
def test_load_states_reads_custom_path(tmp_path: Path) -> None:
path = tmp_path / "states.csv"
path.write_text("state,x,y\nOhio,10,-20\n", encoding="utf-8")
assert load_states(path) == [State("Ohio", 10, -20)]
def test_save_states_to_learn_writes_header_and_states(tmp_path: Path) -> None:
path = tmp_path / "learn.csv"
save_states_to_learn(["Ohio", "Texas"], path)
assert _read_rows(path) == [[STATE_COLUMN], ["Ohio"], ["Texas"]]
def test_save_states_to_learn_writes_only_header_when_nothing_missing(
tmp_path: Path,
) -> None:
path = tmp_path / "learn.csv"
save_states_to_learn([], path)
assert _read_rows(path) == [[STATE_COLUMN]]
def test_save_states_to_learn_lists_47_rows_after_three_guesses(
tmp_path: Path,
) -> None:
path = tmp_path / "learn.csv"
missing = get_missing_states(load_states(), ["Alabama", "Ohio", "Texas"])
save_states_to_learn(missing, path)
assert len(_read_rows(path)) - 1 == NUMBER_OF_STATES - 3