diff --git a/archeryutils/rounds.py b/archeryutils/rounds.py index 1a1a7ca..57c7cca 100644 --- a/archeryutils/rounds.py +++ b/archeryutils/rounds.py @@ -42,6 +42,9 @@ class Pass: def __init__(self, n_arrows: int, target: Target) -> None: self.n_arrows = abs(n_arrows) self.target = target + if not isinstance(self.target, Target): + msg = "The target passed to a Pass should be of type Target." + raise TypeError(msg) @classmethod def at_target( # noqa: PLR0913 @@ -202,6 +205,12 @@ def __init__( # noqa: PLR0913 ) -> None: self.name = name self.passes = list(passes) + if not self.passes: + msg = "passes must contain at least one Pass object but none supplied." + raise ValueError(msg) + if any(not isinstance(x, Pass) for x in self.passes): + msg = "passes in a Round object should be an iterable of Pass objects." + raise TypeError(msg) self.location = location self.body = body self.family = family diff --git a/archeryutils/tests/test_rounds.py b/archeryutils/tests/test_rounds.py index 625383f..970146d 100644 --- a/archeryutils/tests/test_rounds.py +++ b/archeryutils/tests/test_rounds.py @@ -1,6 +1,6 @@ """Tests for Pass and Round classes.""" -from typing import Union +from typing import Iterable, Union import pytest @@ -35,6 +35,14 @@ def test_init(self) -> None: assert test_pass.target == _target assert test_pass.n_arrows == 36 + def test_invalid_target(self) -> None: + """Check that Pass raises a TypeError for invalid target.""" + with pytest.raises( + TypeError, + match="The target passed to a Pass should be of type Target.", + ): + Pass(36, 42) # type: ignore[arg-type] + def test_at_target_constructor(self) -> None: """Check indirect initialisation of a Pass with target parameters.""" test_pass = Pass.at_target(36, "5_zone", 122, 50) @@ -175,6 +183,29 @@ def test_init_with_iterable_passes(self) -> None: assert list_.passes == tuple_.passes == iterable_.passes + @pytest.mark.parametrize( + "badpass", + [ + pytest.param([]), + pytest.param(()), + ], + ) + def test_init_with_empty_passes(self, badpass: Iterable) -> None: + """Check that Round raises a ValueError for empty passes iterable.""" + with pytest.raises( + ValueError, + match="passes must contain at least one Pass object but none supplied.", + ): + Round("My Round Name", badpass) # type: ignore[arg-type] + + def test_init_with_incorrect_type_passes(self) -> None: + """Check that Round raises a TypeError for passes not containing Pass.""" + with pytest.raises( + TypeError, + match="passes in a Round object should be an iterable of Pass objects.", + ): + Round("My Round Name", ["a", "b", "c"]) # type: ignore[list-item] + def test_repr(self) -> None: """Check Pass string representation.""" test_round = Round("Name", [Pass(36, _target)])