pytest.raises 的假设状态测试不报告步骤顺序
Hypothesis stateful testing with pytest.raises doesn't report sequence of steps
我想写一个 hypothesis.stateful.RuleBasedStateMachine
断言在某些情况下会引发异常。 pytest
提供了 raises
上下文管理器来编写关于异常的测试。如果我在 hypothesis.stateful.rule
中使用 pytest.raises
,导致测试失败的步骤顺序是 not 报告。
在没有 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
之外,还可以做些什么来缓解这种情况,即确保打印出步骤顺序?
事实证明,如果规则引发 BaseException
或非 Exception
子类,则不会打印这些步骤。 pytest.raises(...)
如果没有得到预期的异常,就会引发这样的错误,而你就是这样。
https://github.com/HypothesisWorks/hypothesis/issues/1372
既然已经确定,这并不是一个特别严重的错误 - 感谢您通过报告可重现的案例参与其中! - 所以我们应该尽快修复。
更新:此错误已于 2018 年 7 月 3 日在 Hypothesis 3.65.1 中修复。
我想写一个 hypothesis.stateful.RuleBasedStateMachine
断言在某些情况下会引发异常。 pytest
提供了 raises
上下文管理器来编写关于异常的测试。如果我在 hypothesis.stateful.rule
中使用 pytest.raises
,导致测试失败的步骤顺序是 not 报告。
在没有 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
之外,还可以做些什么来缓解这种情况,即确保打印出步骤顺序?
事实证明,如果规则引发 BaseException
或非 Exception
子类,则不会打印这些步骤。 pytest.raises(...)
如果没有得到预期的异常,就会引发这样的错误,而你就是这样。
https://github.com/HypothesisWorks/hypothesis/issues/1372
既然已经确定,这并不是一个特别严重的错误 - 感谢您通过报告可重现的案例参与其中! - 所以我们应该尽快修复。
更新:此错误已于 2018 年 7 月 3 日在 Hypothesis 3.65.1 中修复。