Гипотеза о проверке состояния с помощью pytest.raises не сообщает о последовательности шагов - PullRequest
0 голосов
/ 27 июня 2018

Я хочу написать hypothesis.stateful.RuleBasedStateMachine, который утверждает, что исключение возникает при определенных обстоятельствах. pytest предоставляет менеджер контекста raises для написания тестов об исключениях. Если я использую pytest.raises внутри hypothesis.stateful.rule, последовательность шагов, приводящих к неудаче теста, не сообщается , а не .

Перезапись правила без pytest.raises приводит к желаемому поведению: отображается последовательность шагов.

Вот пример кода:

from os import getenv

from pytest import raises

from hypothesis.stateful   import RuleBasedStateMachine, rule

SHOW_PROBLEM = getenv('SHOW_PROBLEM') == 'yes'


# A state machine which asserts that an exception is raised in under some condition
class FifthCallShouldRaiseValueError(RuleBasedStateMachine):

    def __init__(self):
        super().__init__()
        self.model = Model()
        self.count = 0

    if SHOW_PROBLEM:

        # This version does NOT report the rule sequence
        @rule()
        def the_rule(self):
            self.count += 1
            if self.count > 4:
                with raises(ValueError):
                    self.model.method()

    else:

        # This version DOES report the rule sequence
        @rule()
        def the_rule(self):
            self.count += 1
            if self.count > 4:
                try:
                    self.model.method()
                except ValueError: assert True
                except           : assert False
                else             : assert False


T = FifthCallShouldRaiseValueError.TestCase


# A model that deliberately fails the test, triggering reporting of
# the sequence of steps which lead to the failure.
class Model:

    def __init__(self):
        self._count = 0

    def method(self):
        self._count += 1
        if self._count > 4:
            # Deliberate mistake: raise wrong exception type
            raise TypeError

Чтобы увидеть разницу в поведении, выполните тест с помощью

  • SHOW_PROBLEM=yes pytest <...>
  • SHOW_PROBLEM=no pytest <...>

Во втором случае вывод будет показывать

state = FifthCallShouldRaiseValueError()
state.the_rule()
state.the_rule()
state.the_rule()
state.the_rule()
state.the_rule()
state.teardown()

Эта последовательность шагов отсутствует в выходных данных в первом случае. Это желательно: последовательность должна быть показана в обоих случаях.

pytest.raises повышает Failed: DID NOT RAISE <class 'ValueError'>, в то время как рукописная версия повышает AssertionError. Первый более информативен, когда речь идет о невозможности вызвать требуемое исключение, но каким-то образом препятствует hypothesis.stateful сообщать о последовательности шагов, что говорит нам о том, как мы попали в это состояние, и часто является наиболее интересной частью выход.

Что можно сделать, чтобы смягчить это, то есть, чтобы распечатать последовательность шагов, кроме того, чтобы не использовать pytest.raises?

1 Ответ

0 голосов
/ 30 июня 2018

Оказывается, что шаги не печатаются, если правило поднимает BaseException или не Exception подкласс. pytest.raises(...) выдает именно такую ​​ошибку, если она не получает ожидаемого исключения, и вот вы здесь.

https://github.com/HypothesisWorks/hypothesis/issues/1372

Теперь это не особо грубая ошибка, так как она была обнаружена - и спасибо за ваше участие в этом, сообщив о воспроизводимом случае! - так что мы должны скоро найти решение.

Обновление: эта ошибка была исправлена ​​в Гипотеза 3.65.1 , 2018-07-03.

...