Read and write the high score file and show the stored high score
Refs #24 Refs #25 Refs #26 Task: MIL-004#2 Task: MIL-004#3 Task: MIL-004#4
This commit is contained in:
+9
-2
@@ -286,16 +286,23 @@ def make_food(monkeypatch: pytest.MonkeyPatch) -> Any:
|
||||
return module.Food()
|
||||
|
||||
|
||||
def make_scoreboard(monkeypatch: pytest.MonkeyPatch) -> Any:
|
||||
def make_scoreboard(
|
||||
monkeypatch: pytest.MonkeyPatch, path: str | Path | None = None
|
||||
) -> Any:
|
||||
"""Make a real `Scoreboard` whose base class is the fake `Turtle`.
|
||||
|
||||
When `path` is given it is the high score file; otherwise the default
|
||||
`data.txt` is used, which `conftest.py` has moved into a temporary directory.
|
||||
|
||||
The result is typed `Any` because it has the methods of `Scoreboard`
|
||||
(`increase_score`) and the recording methods of the fake base class (`calls`)
|
||||
at once.
|
||||
"""
|
||||
install_fake_turtle(monkeypatch)
|
||||
module = importlib.import_module("snake_game.scoreboard")
|
||||
return module.Scoreboard()
|
||||
if path is None:
|
||||
return module.Scoreboard()
|
||||
return module.Scoreboard(str(path))
|
||||
|
||||
|
||||
def imports_turtle_or_tkinter(module_name: str) -> bool:
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
"""Tests of reading and writing the high score file, with temporary files."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from snake_game.high_score_file import read_high_score, write_high_score
|
||||
|
||||
|
||||
def test_read_returns_the_stored_number(tmp_path: Path) -> None:
|
||||
path = tmp_path / "data.txt"
|
||||
path.write_text("17", encoding="utf-8")
|
||||
|
||||
assert read_high_score(str(path)) == 17
|
||||
|
||||
|
||||
def test_read_accepts_a_trailing_newline(tmp_path: Path) -> None:
|
||||
path = tmp_path / "data.txt"
|
||||
path.write_text("5\n", encoding="utf-8")
|
||||
|
||||
assert read_high_score(str(path)) == 5
|
||||
|
||||
|
||||
def test_read_creates_a_missing_file_holding_0(tmp_path: Path) -> None:
|
||||
path = tmp_path / "data.txt"
|
||||
|
||||
assert read_high_score(str(path)) == 0
|
||||
assert path.read_text(encoding="utf-8") == "0"
|
||||
|
||||
|
||||
def test_read_gives_0_for_an_empty_file_and_leaves_it_empty(tmp_path: Path) -> None:
|
||||
path = tmp_path / "data.txt"
|
||||
path.write_text("", encoding="utf-8")
|
||||
|
||||
assert read_high_score(str(path)) == 0
|
||||
assert path.read_text(encoding="utf-8") == ""
|
||||
|
||||
|
||||
def test_read_gives_0_for_text_that_is_not_a_whole_number(tmp_path: Path) -> None:
|
||||
path = tmp_path / "data.txt"
|
||||
path.write_text("many", encoding="utf-8")
|
||||
|
||||
assert read_high_score(str(path)) == 0
|
||||
assert path.read_text(encoding="utf-8") == "many"
|
||||
|
||||
|
||||
def test_read_gives_0_for_a_negative_number(tmp_path: Path) -> None:
|
||||
path = tmp_path / "data.txt"
|
||||
path.write_text("-4", encoding="utf-8")
|
||||
|
||||
assert read_high_score(str(path)) == 0
|
||||
assert path.read_text(encoding="utf-8") == "-4"
|
||||
|
||||
|
||||
def test_read_gives_0_for_bytes_that_are_not_utf_8(tmp_path: Path) -> None:
|
||||
path = tmp_path / "data.txt"
|
||||
path.write_bytes(b"\xff\xfe\x00\x80")
|
||||
|
||||
assert read_high_score(str(path)) == 0
|
||||
assert path.read_bytes() == b"\xff\xfe\x00\x80"
|
||||
|
||||
|
||||
def test_write_replaces_the_old_content(tmp_path: Path) -> None:
|
||||
path = tmp_path / "data.txt"
|
||||
path.write_text("123456", encoding="utf-8")
|
||||
|
||||
write_high_score(9, str(path))
|
||||
|
||||
assert path.read_text(encoding="utf-8") == "9"
|
||||
|
||||
|
||||
def test_write_creates_the_file(tmp_path: Path) -> None:
|
||||
path = tmp_path / "data.txt"
|
||||
|
||||
write_high_score(3, str(path))
|
||||
|
||||
assert path.read_text(encoding="utf-8") == "3"
|
||||
|
||||
|
||||
def test_the_file_is_closed_after_reading_and_writing(tmp_path: Path) -> None:
|
||||
path = tmp_path / "data.txt"
|
||||
|
||||
write_high_score(2, str(path))
|
||||
read_high_score(str(path))
|
||||
path.unlink() # fails on Windows while a handle is still open
|
||||
|
||||
assert not path.exists()
|
||||
|
||||
|
||||
def test_the_default_path_is_data_txt_in_the_working_directory(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
write_high_score(4)
|
||||
|
||||
assert (tmp_path / "data.txt").read_text(encoding="utf-8") == "4"
|
||||
assert read_high_score() == 4
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import importlib
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -129,6 +130,85 @@ def test_the_score_text_shows_both_scores_while_playing(
|
||||
assert scoreboard.calls[-1][1][0] == "Score: 1 High Score: 2"
|
||||
|
||||
|
||||
def test_scoreboard_shows_the_stored_high_score_at_start(
|
||||
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
||||
) -> None:
|
||||
path = tmp_path / "scores.txt"
|
||||
path.write_text("12", encoding="utf-8")
|
||||
|
||||
scoreboard = make_scoreboard(monkeypatch, path)
|
||||
|
||||
assert scoreboard.high_score == 12
|
||||
assert scoreboard.calls[-1][1][0] == "Score: 0 High Score: 12"
|
||||
|
||||
|
||||
def test_a_new_high_score_is_written_to_the_file_on_reset(
|
||||
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
||||
) -> None:
|
||||
path = tmp_path / "scores.txt"
|
||||
path.write_text("1", encoding="utf-8")
|
||||
scoreboard = make_scoreboard(monkeypatch, path)
|
||||
for _ in range(2):
|
||||
scoreboard.increase_score()
|
||||
|
||||
scoreboard.reset()
|
||||
|
||||
assert path.read_text(encoding="utf-8") == "2"
|
||||
|
||||
|
||||
def test_a_lower_score_does_not_write_the_file(
|
||||
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
||||
) -> None:
|
||||
path = tmp_path / "scores.txt"
|
||||
path.write_text("5", encoding="utf-8")
|
||||
scoreboard = make_scoreboard(monkeypatch, path)
|
||||
scoreboard.increase_score()
|
||||
path.write_text("sentinel", encoding="utf-8")
|
||||
|
||||
scoreboard.reset()
|
||||
|
||||
assert path.read_text(encoding="utf-8") == "sentinel"
|
||||
assert scoreboard.high_score == 5
|
||||
|
||||
|
||||
def test_an_equal_score_does_not_write_the_file(
|
||||
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
||||
) -> None:
|
||||
path = tmp_path / "scores.txt"
|
||||
path.write_text("2", encoding="utf-8")
|
||||
scoreboard = make_scoreboard(monkeypatch, path)
|
||||
scoreboard.increase_score()
|
||||
scoreboard.increase_score()
|
||||
path.write_text("sentinel", encoding="utf-8")
|
||||
|
||||
scoreboard.reset()
|
||||
|
||||
assert path.read_text(encoding="utf-8") == "sentinel"
|
||||
|
||||
|
||||
def test_a_missing_file_shows_high_score_0_and_is_created(
|
||||
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
||||
) -> None:
|
||||
path = tmp_path / "scores.txt"
|
||||
|
||||
scoreboard = make_scoreboard(monkeypatch, path)
|
||||
|
||||
assert scoreboard.calls[-1] == START_TEXT
|
||||
assert path.read_text(encoding="utf-8") == "0"
|
||||
|
||||
|
||||
def test_a_damaged_file_shows_high_score_0(
|
||||
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
||||
) -> None:
|
||||
path = tmp_path / "scores.txt"
|
||||
path.write_text("not a number", encoding="utf-8")
|
||||
|
||||
scoreboard = make_scoreboard(monkeypatch, path)
|
||||
|
||||
assert scoreboard.high_score == 0
|
||||
assert scoreboard.calls[-1] == START_TEXT
|
||||
|
||||
|
||||
def test_scoreboard_has_no_game_over_any_more(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user