diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef9ed39..be54212 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,8 @@ jobs: # setuptools_scm requires a non-shallow clone of the repository fetch-depth: 0 + - uses: tlambert03/setup-qt-libs@v1 + - name: Linux setup if: runner.os == 'Linux' # qt requires some system libraries on linux that are not installed by default diff --git a/pyproject.toml b/pyproject.toml index 782b514..ba5e32f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,8 @@ tests = [ "pytest-randomly", "pytest-qt", "pytest-xvfb", - "ipytest" + "ipytest", + "hypothesis", ] # Command line scripts installed as part of the installation diff --git a/tests/test_board_property.py b/tests/test_board_property.py new file mode 100644 index 0000000..1a9d6d5 --- /dev/null +++ b/tests/test_board_property.py @@ -0,0 +1,42 @@ +from __future__ import annotations +from effective_software_testing.board import Board +from hypothesis import given, assume, example +import hypothesis.strategies as st + + +# sample n from integers in the range 0 <= n <= 99 +@given(n=st.integers(min_value=0, max_value=99)) +@example(n=3) # always include n=3 +def test_property_empty_board_game_not_over(n: int) -> None: + board = Board(n) + assert board.n == n + assert board.game_is_over is False + + +@given(n=st.integers(1, 12), x=st.integers(0, 11), y=st.integers(0, 11)) +def test_property_empty_board_is_empty_with_assume(n: int, x: int, y: int) -> None: + assume(x < n) # if x >= n we re-sample n,x,y + assume(y < n) + # assume works but quickly gets inefficient if many inputs do not satisfy our assumptions + board = Board(n) + assert board.square(x, y) is None + + +# using composite is a more efficient way to sample from our desired distribution of values +@st.composite +def sample_valid_n_x_y(draw: st.DrawFn) -> tuple[int, int, int]: + max_board_n = 12 + n = draw(st.integers(1, max_board_n)) + x = draw(st.integers(0, n - 1)) + y = draw(st.integers(0, n - 1)) + return n, x, y + + +@given(n_x_y=sample_valid_n_x_y()) +def test_property_empty_board_is_empty_with_composite( + n_x_y: tuple[int, int, int] +) -> None: + # no assume required here as all the x,y we generate are < n + n, x, y = n_x_y + board = Board(n) + assert board.square(x, y) is None