Skip to content

Commit

Permalink
Add example code with advanced topic tests
Browse files Browse the repository at this point in the history
  • Loading branch information
andreas-el committed Sep 13, 2023
1 parent de4e9f2 commit 866bbba
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 0 deletions.
5 changes: 5 additions & 0 deletions examples/adv_testing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
python treasurehunt.py
python -m doctest -v terrain_slope.py
pytest -n auto -svv test_terrain_slope.py
pytest -n auto -svv test_treasure_search.py
pytest -n auto -svv test_hypothesis_slope.py
19 changes: 19 additions & 0 deletions examples/adv_testing/terrain_slope.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import math


def calculate_slope(a: tuple[float, float], b: tuple[float, float]) -> float:
"""
>>> calculate_slope((1.0, 0.0), (2.0, 0.0))
0.0
>>> calculate_slope((1.0, 0.0), (2.0, 1.0))
1.0
>>> calculate_slope((1.0, 0.0), (2.0, "mystring"))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/ANDRLI/Project/tdd/treasurehunt.py", line 35, in calculate_slope
return (b[1] - a[1]) / (b[0] - a[0])
TypeError: unsupported operand type(s) for -: 'str' and 'float'
"""

# (y2 - y1) / (x2 - x1)
return (b[1] - a[1]) / (b[0] - a[0])
19 changes: 19 additions & 0 deletions examples/adv_testing/test_another_treasure_search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from unittest.mock import patch

import pytest

import treasurehunt


@patch("treasurehunt.read_coordinates")
def test_another_treasure(mock_read_coordinates):
mock_read_coordinates.return_value = [
(0.0, 0.0),
(1.0, 0.0),
(2.0, 0.5),
(3.0, 1.0),
(4.0, 4.0),
]

point = treasurehunt.treasure_search()
assert pytest.approx(point) == (4.0, 4.0)
14 changes: 14 additions & 0 deletions examples/adv_testing/test_hypothesis_slope.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from hypothesis import given, reproduce_failure
from hypothesis import strategies as st

from treasurehunt import calculate_slope


@given(
st.floats(min_value=0.0, max_value=10.0),
st.floats(min_value=0.0, max_value=10.0),
st.floats(min_value=0.0, max_value=10.0),
st.floats(min_value=0.0, max_value=10.0),
)
def test_that_calculate_slope_does_not_raise(_x1, _y1, _x2, _y2):
calculate_slope((_x1, _y1), (_x2, _y2))
22 changes: 22 additions & 0 deletions examples/adv_testing/test_terrain_slope.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import pytest

from terrain_slope import calculate_slope


def test_simple_slopes():
assert pytest.approx(calculate_slope((1.0, 0.0), (2.0, 1.0))) == 1.0
assert pytest.approx(calculate_slope((1.0, 0.0), (2.0, 0.0))) == 0.0
assert pytest.approx(calculate_slope((1.0, 0.0), (2.0, -1.0))) == -1.0


@pytest.mark.parametrize(
"_x1, _y1, _x2, _y2, result",
[
(1.0, 1.0, 2.0, 2.0, 1.0),
(2.0, 3.0, 4.0, 4.0, 0.5),
(1.0, 1.0, 2.0, 0.0, -1.0),
(2.0, 4.0, 4.0, 3.0, -0.5),
],
)
def test_input_slopes(_x1, _y1, _x2, _y2, result):
assert pytest.approx(calculate_slope((_x1, _y1), (_x2, _y2))) == result
25 changes: 25 additions & 0 deletions examples/adv_testing/test_treasure_search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from pathlib import Path
from typing import Union

import pytest

import treasurehunt


def test_find_treasure(monkeypatch):
def mock_read_coordinates(file_name: Union[str, Path]):
return [(0.0, 0.0), (1.0, 0.0), (2.0, 2.0)]

monkeypatch.setattr(treasurehunt, "read_coordinates", mock_read_coordinates)
point = treasurehunt.treasure_search()
assert pytest.approx(point) == (2.0, 2.0)


def test_find_treasure_raises_on_flat_ground(monkeypatch):
def mock_read_coordinates(file_name: Union[str, Path]):
return [(0.0, 0.0), (1.0, 0.0), (2.0, 0.0)]

monkeypatch.setattr(treasurehunt, "read_coordinates", mock_read_coordinates)

with pytest.raises(RuntimeError, match="Cannot find treasure"):
treasurehunt.treasure_search()
47 changes: 47 additions & 0 deletions examples/adv_testing/treasurehunt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from pathlib import Path
from typing import List, Tuple, Union

from terrain_slope import calculate_slope


def read_coordinates(file_name: Union[str, Path]) -> List[Tuple[float, float]]:
"""
Will read a file of comma separated strings and turn it
into a list
"""
coordinates = []
with open(file_name, "r", encoding="utf-8") as input_file:
for line in input_file:
_x, _y = line.strip().split(",")
coordinates.append((float(_x), float(_y)))
return sorted(coordinates)


def treasure_search() -> Tuple[float, float]:
"""
Loads a treasure map, and step by step calculates the slope
to find the treasure (if any) and returns (x, y) of that point
"""
treasure_map_file = "../../maps/treasure_map_1.txt"
treasure_map = read_coordinates(treasure_map_file)
previous_pos = None

for current_pos in treasure_map:
if previous_pos:
slope = calculate_slope(previous_pos, current_pos)

if slope >= 1.0:
print(f"Found treasure at ({current_pos[0]}, {current_pos[1]})")
return current_pos

previous_pos = current_pos

raise RuntimeError("Cannot find treasure")


def main():
treasure_search()


if __name__ == "__main__":
main()

0 comments on commit 866bbba

Please sign in to comment.