Order imports, format with ruff, make the account key constants Final so mypy --strict accepts them, and type the test helpers. Configure ruff and mypy in pyproject.toml and pin the dev tool versions. All modules, classes and functions already carry Doxygen comments; doxygen Doxyfile builds without warnings. Task: MIL-004#2 Closes #18
89 lines
2.6 KiB
Python
89 lines
2.6 KiB
Python
"""@file test_game_logic.py
|
|
@brief Tests for the pure game functions.
|
|
"""
|
|
|
|
import random
|
|
|
|
import pytest
|
|
|
|
from higher_lower.constants import KEY_NAME
|
|
from higher_lower.game_data import Account, data
|
|
from higher_lower.game_logic import (
|
|
check_answer,
|
|
format_data,
|
|
get_random_account,
|
|
pick_pair,
|
|
)
|
|
|
|
|
|
def test_get_random_account_returns_an_entry_of_the_data() -> None:
|
|
"""@brief The drawn account comes from the data set."""
|
|
assert get_random_account(rng=random.Random(1)) in data
|
|
|
|
|
|
def test_get_random_account_is_repeatable_with_a_seed() -> None:
|
|
"""@brief The same seed draws the same account."""
|
|
assert get_random_account(rng=random.Random(7)) == get_random_account(
|
|
rng=random.Random(7)
|
|
)
|
|
|
|
|
|
def test_pick_pair_never_returns_the_same_account() -> None:
|
|
"""@brief A and B are always different entries."""
|
|
rng = random.Random(0)
|
|
for _ in range(200):
|
|
first, second = pick_pair(rng=rng)
|
|
assert first[KEY_NAME] != second[KEY_NAME]
|
|
|
|
|
|
def test_pick_pair_with_two_accounts_returns_both() -> None:
|
|
"""@brief With only two accounts, the pair holds both of them."""
|
|
two = data[:2]
|
|
first, second = pick_pair(two, random.Random(3))
|
|
assert {first[KEY_NAME], second[KEY_NAME]} == {a[KEY_NAME] for a in two}
|
|
|
|
|
|
def test_pick_pair_with_one_account_raises() -> None:
|
|
"""@brief A pair cannot be drawn from a single account."""
|
|
with pytest.raises(ValueError):
|
|
pick_pair(data[:1])
|
|
|
|
|
|
def test_format_data_describes_the_account() -> None:
|
|
"""@brief The description holds name, description and country."""
|
|
account: Account = {
|
|
"name": "Nike",
|
|
"follower_count": 109,
|
|
"description": "Sportswear multinational",
|
|
"country": "United States",
|
|
}
|
|
assert (
|
|
format_data(account) == "Nike, a Sportswear multinational, from United States"
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("guess", "a_followers", "b_followers", "expected"),
|
|
[
|
|
("a", 200, 100, True),
|
|
("a", 100, 200, False),
|
|
("b", 100, 200, True),
|
|
("b", 200, 100, False),
|
|
("A", 200, 100, True),
|
|
("B", 100, 200, True),
|
|
("a", 100, 100, True),
|
|
("b", 100, 100, True),
|
|
],
|
|
)
|
|
def test_check_answer(
|
|
guess: str, a_followers: int, b_followers: int, expected: bool
|
|
) -> None:
|
|
"""@brief The answer is right for the higher account, and for either on a tie."""
|
|
assert check_answer(guess, a_followers, b_followers) is expected
|
|
|
|
|
|
def test_check_answer_rejects_an_unknown_choice() -> None:
|
|
"""@brief A guess other than a or b is an error."""
|
|
with pytest.raises(ValueError):
|
|
check_answer("c", 1, 2)
|