Andi
Andi

Reputation: 4865

Handling assertions/exceptions using python-hypothesis

What is considered to be best practice when it comes to property based testing using the hypothesis library with respect to assertions within the program code?

I created a very simple function to show my point. The function simply divides two numbers. I put in an assertion that fails if the denominator is zero.

When I run the test, it fails as soon as hypothesis chooses 0 for parameter b (denominator) due to the assertion error. However, the assertion in the function is meant to handle this particular case.

from hypothesis import given
from hypothesis import strategies as st


def divide(a: float, b: float) -> float:
    assert b != 0, "Denominator must not be zero!"

    return a / b


@given(b=st.floats())
def test_divide(b):
    assert isinstance(divide(100, b), (int, float))

How am I supposed to adjust the code to make the test pass for parameter value b=0? What's a pythonic way?

EDIT:
In my view, the suggested duplicate question (Exception handling and testing with pytest and hypothesis) doesn't solve the issue.

What happens if I were to use the following code?

@given(b=st.floats())
def test_divide(b):
    try:
        assert isinstance(divide(100, b), (int, float))
    except AssertionError:
        assume(False)

As far as I understand it, as soon as the assertion within the try block will be False, the except-path will be executed and the particular test case will be ignored. That is, every real test failure (found by hypothesis) will be ignored.

Compared to the suggested duplicate question, my divide-function will throw an AssertionError rather than a ZeroDivisionError for b=0. Every other failing test case will also cause an AssertionError (try-block).

Upvotes: 0

Views: 578

Answers (1)

user12293134
user12293134

Reputation: 56

@given(b=st.floats())
def test_divide(b):
    assume(b != 0)
    assert isinstance(divide(100, b), (int, float))

assume tells hypothesis that b == 0 is a bad example, and to ignore it.

Bear in mind that with the floats strategy, you're also going to get Nan and -Nan - you can disable this in the strat with allow_infinity=False. Once you're modifying the strat, you may as well also add min_value=1 or min_value=0.00000001 to prevent 0

Upvotes: 4

Related Questions