Property Based Testing With Hypothesis

This is a summary based on this article.

Rather than specifying test cases, define properties that your functions must fulfil, and let hypothesis generate dozens of test cases automatically.

from hypothesis import given, strategies as st

@given(st.integers(), st.integers())
def test_func(a, b):
    # get result
    c = func(a, b)

    # test properties based on the result
    assert c > a

Here @given(st.integers(), st.integers()) indicates the function must work for all integers as a and b. hypothesis will generate many test cases based on this.

  • We can filter out values: st.integers().filter(lambda n: n != 0)
  • Or specify a range: st.integers(min_value=1, max_value=100)
  • Or both!

Other usecases:

  • fuzzing ie. simply make sure your function runs without error for all possible values
def test_func(x)
  • round tripping
def test_func(x)
    assert x == anti_func(func(x))
  • gold standard comparison eg. to validate a new optimisation
def test_func(x)
    assert old_func(x) == func(x)

However, the tests may pass as false positive if you don't fully define the properties.

If in doubt you can also include regular tests.