# Lets play testing --- # Unit testing ```python def mymax(x,y): if x >= y: return x else: return y ``` -- ## ... the old way ```python def test_known_values(): assert mymax(1,2) == 2 assert mymax(1,3) == 3 assert mymax(4,1) == 4 assert mymax(3,1) == 3 assert mymax(2,1) == 2 assert mymax(4,4) == 4 assert mymax(4,19) == 19 assert mymax(2,34) == 34 assert mymax(8,21) == 21 ``` So much code and you haven't even looked at negative numbers. --- # Unit testing ```python def mymax(x,y): if x >= y: return x else: return y ``` ## ... with property based testing ```python def test_is_one_of_the_arguments(x, y): assert mymax(x, y) in [x, y] def test_is_bigger_than_every_argument(x, y): assert mymax(x, y) >= x assert mymax(x, y) >= y ``` ...for all values of `x` and `y`. --- # Multiply and divide ```python from hypothesis import given from hypothesis.strategies import integers @given(integers(), integers()) def test_multiply_and_divide(x, y): assert (x * y) / y == x ``` -- ```toml x = 0, y = 0 @given(integers(), integers()) def test_multiply_and_divide(x, y): > assert (x * y) / y == x E ZeroDivisionError: division by zero multiply_and_divide.py:6: ZeroDivisionError --------------------------------- Hypothesis ------------------------------------ Falsifying example: test_multiply_and_divide(x=0, y=0) ``` --- # Commutative ```python from hypothesis import given from hypothesis.strategies import integers @given(integers(), integers()) def test_commutative(x, y): assert x+y == y+x ``` -- ```toml =========================== 1 passed in 0.32 seconds ============================ ``` Wouldn't have worked for strings or lists instead of ints. --- # Maximum is biggest ```python from hypothesis import given from hypothesis.strategies import lists, integers @given(lists(integers())) def test_maximum_is_biggest(l): m = max(l) # maximum of a list for x in l: assert x <= m ``` -- ```toml l = [] @given(lists(integers())) def test_maximum_is_biggest(l): > m = max(l) # maximum of a list E ValueError: max() arg is an empty sequence maximum_is_biggest.py:6: ValueError --------------------------------- Hypothesis ------------------------------------ Falsifying example: test_maximum_is_biggest(l=[]) ``` --- # Average is in bounds ```python from hypothesis import given from hypothesis.strategies import lists, floats def average(ls): return sum(ls)/len(ls) @given( lists( floats(allow_nan=False, allow_infinity=False), min_size=1 ) ) def test_average_is_in_bounds(l): assert min(l) <= average(l) assert average(l) <= max(l) ``` -- ```toml average_is_in_bounds.py:8: MultipleFailures --------------------------------- Hypothesis ------------------------------------ Falsifying example: test_average_is_in_bounds( l=[9.9792015476736e+291, 1.7976931348623157e+308] ) ... AssertionError: assert inf <= 1.7976931348623157e+308 ``` ??? - example of a bug you would not have expected - that implementation of average is buggy --- # Additional notes about hypothesis - __shrink__ falsifying examples: get (x=0, y=0) instead of (x=2048, y=0) - __own strategies and datatypes__ can be generated - property based tests can live __side by side__ with your traditional unit tests. - __example values__ can be specified - __limit the number__ of gernerated tests if you want to safe time and space. --- # Thank you ## .. and use hypothesis for your tests