Обработка утверждений / исключений с использованием гипотезы Python

Что считается наилучшей практикой, когда речь идет о тестировании на основе свойств с использованием библиотеки hypothesis в отношении утверждений в программном коде?

Я создал очень простую функцию, чтобы показать мою точку зрения. Функция просто делит два числа. Я делаю утверждение, которое не работает, если знаменатель равен нулю.

Когда я запускаю тест, он терпит неудачу, как только hypothesis выбирает 0 для параметра b (знаменатель) из-за ошибки утверждения. Однако утверждение в функции предназначено для обработки этого конкретного случая.

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))

Как мне настроить код, чтобы пройти тест для значения параметра b=0? Что такое питонический путь?

РЕДАКТИРОВАТЬ:
На мой взгляд, предлагаемый повторяющийся вопрос (Исключение обработка и тестирование с помощью pytest и hypothesis) не решает проблему.

Что произойдет, если я использую следующий код?

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

Насколько я понимаю, как только утверждение в блоке try будет False, будет выполнен except-path, а конкретный тестовый пример будет проигнорирован. То есть каждый реальный сбой теста (обнаруженный hypothesis) будет проигнорирован.

По сравнению с предложенным повторяющимся вопросом моя divide-функция выдаст AssertionError, а не ZeroDivisionError для b=0. Каждый другой неудачный тестовый пример также вызовет AssertionError (try-block).


person Andi    schedule 18.08.2020    source источник
comment
Отвечает ли это на ваш вопрос? Обработка исключений и тестирование с помощью pytest и гипотез   -  person Georgy    schedule 18.08.2020
comment
Я так не думаю. Я отредактировал свой исходный вопрос.   -  person Andi    schedule 19.08.2020


Ответы (1)


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

Предположим, что гипотеза о том, что b == 0 - плохой пример, говорит о том, что она игнорируется.

Имейте в виду, что со стратегией с плавающей запятой вы также получите Nan и -Nan - вы можете отключить это в страте с помощью allow_infinity=False. После изменения страты вы также можете добавить min_value=1 или min_value=0.00000001, чтобы предотвратить 0

person user12293134    schedule 18.08.2020
comment
Вероятно, вы хотите, чтобы allow_nan=False исключил nan; allow_infinity=False вместо этого отключит +inf и -inf ;-) - person Zac Hatfield-Dodds; 21.08.2020