test_suite.py in Python
A pytest file as it looks in a real project: fixtures, parametrize, marks.
"""Run me with: pytest test_suite.py -v"""
import pytest
# ---- the code under test ---------------------------------------------
class Scorer:
def __init__(self, target_tpm: int = 90):
if target_tpm <= 0:
raise ValueError("target must be positive")
self.target_tpm = target_tpm
self.history: list[int] = []
def stars(self, tpm: float, accuracy: float) -> int:
if accuracy < 0 or accuracy > 100:
raise ValueError(f"accuracy out of range: {accuracy}")
earned = 1
if accuracy >= 95:
earned = 2
if accuracy >= 98 and tpm >= self.target_tpm:
earned = 3
self.history.append(earned)
return earned
@property
def best(self) -> int:
return max(self.history, default=0)
# ---- the tests -------------------------------------------------------
@pytest.fixture
def scorer():
return Scorer(target_tpm=90)
@pytest.mark.parametrize("tpm,accuracy,expected", [
(60.0, 90.0, 1),
(60.0, 96.0, 2),
(95.0, 99.0, 3),
(80.0, 99.0, 2),
])
def test_stars_by_tier(scorer, tpm, accuracy, expected):
assert scorer.stars(tpm, accuracy) == expected
def test_history_and_best(scorer):
scorer.stars(95.0, 99.0)
scorer.stars(50.0, 80.0)
assert scorer.history == [3, 1]
assert scorer.best == 3
def test_empty_history_has_no_best(scorer):
assert scorer.best == 0
@pytest.mark.parametrize("accuracy", [-1.0, 101.0])
def test_rejects_impossible_accuracy(scorer, accuracy):
with pytest.raises(ValueError, match="out of range"):
scorer.stars(90.0, accuracy)
def test_rejects_a_zero_target():
with pytest.raises(ValueError, match="positive"):
Scorer(target_tpm=0)
def test_target_is_respected(monkeypatch):
strict = Scorer(target_tpm=200)
assert strict.stars(150.0, 99.0) == 2
@pytest.mark.parametrize("target", [1, 90, 500])
def test_any_positive_target_builds(target):
assert Scorer(target).target_tpm == target
How it works
- The module under test sits at the top, so the file is self-contained.
- Fixtures build the objects; parametrize covers the cases.
- Running pytest on this file exercises every path below.
Keywords and builtins used here
Scorerassertbestclassdeffloatifintlistmaxraisereturnscorerselfstarstest_any_positive_target_buildstest_empty_history_has_no_besttest_history_and_besttest_rejects_a_zero_targettest_rejects_impossible_accuracytest_stars_by_tiertest_target_is_respectedwith
The run, in numbers
- Lines
- 78
- Characters to type
- 1797
- Tokens
- 408
- Three-star pace
- 110 tpm
At the three-star pace of 110 tokens a minute, this run takes about 223 seconds.
Step 1 of 1 in Encore, step 9 of 9 in Testing with pytest.