【问题标题】:Why does my simple, finite hypothesis test never stop?为什么我的简单、有限假设检验永远不会停止?
【发布时间】:2019-07-08 03:05:19
【问题描述】:

我正在运行一个带有假设 4.24.6 和 pytest-5.0.0 的测试套件。我的测试有一组有限的可能输入,但假设永远不会完成测试。

我已将其简化为以下最小示例,我以 pytest test.py 运行它

from hypothesis import given
import hypothesis.strategies as st


@given(x=st.just(0)
         | st.just(1),
       y=st.just(0)
         | st.just(1)
         | st.just(2))
def test_x_y(x, y):
    assert True

我希望它在这里尝试所有六种组合然后成功。或者可能是其中的一小部分以检查片状。相反,它会无限期地运行,(经过大约 15 分钟的测试,我将其杀死。)

如果我中断测试,回溯似乎表明它只是不断生成新示例。

我在这里做错了什么?

【问题讨论】:

  • 这显然是在 4.10 版本中首次出现的回归。在 4.9 版本中,测试在 0.12 秒内通过,而在 4.10 及更高版本中,测试不会在超过 1 分钟后停止。我会创建一个new issue,或者召唤Zac Hatfield-Dodds 并询问他。
  • 我还在研究这个,但这显然是一个错误!未来详情将发布在github.com/HypothesisWorks/hypothesis/issues/2027

标签: python pytest python-hypothesis


【解决方案1】:

这似乎与hypothesis 尝试生成的成功测试的数量有关:

>>> from hypothesis import given, strategies as st
>>> @given(st.integers(0,1), st.integers(0,2))
... def test(x, y):
...   print(x, y)
...   assert True
... 
>>> test()
0 0
1 1
1 0
1 2
1 1
0 1
0 0
1 2
0 2
0 2
1 0
1 2
0 1
0 1
1 2
[snip…]

看,this part of the docs, for instance,成功的测试用例的默认数量应该是 100。因此,尝试生成越来越多的数据以仅限制为 6 个用例很快就会找不到这 6 个用例之一。

最简单的方法是只需 limit the amount of examples 即可通过此测试:

>>> from hypothesis import settings
>>> @settings(max_examples=30)
... @given(st.integers(0,1), st.integers(0,2))
... def test(x, y):
...   print(x, y)
...   assert True
... 
>>> test()
0 0
1 1
1 0
0 2
1 2
0 1
0 1
1 1
1 0
1 1
0 1
1 2
1 1
0 0
0 2
0 2
0 0
1 2
1 0
0 1
1 0
1 0
0 1
1 2
1 1
0 2
0 0
1 2
0 0
0 2

鉴于测试用例的数量很少,另一种方法是使用@example 将它们全部显式并询问hypothesisonly run those explicit examples

>>> from hypothesis import given, example, settings, Phase, strategies as st
>>> @settings(phases=(Phase.explicit,))
... @given(x=st.integers(), y=st.integers())
... @example(x=0, y=0)
... @example(x=0, y=1)
... @example(x=0, y=2)
... @example(x=1, y=0)
... @example(x=1, y=1)
... @example(x=1, y=2)
... def test(x, y):
...   print(x, y)
...   assert True
... 
>>> test()
0 0
0 1
0 2
1 0
1 1
1 2

还要注意st.just(0) | st.just(1) 等同于st.one_of(st.just(0), st.just(1)),所以选择一种方法并坚持下去,但不要混用它们。

【讨论】:

  • 感谢最后的提示,我已经让示例变得更简单了。这个问题似乎可能是一个错误,因为这实际上在 4.9 中按预期工作
【解决方案2】:

这个错误已在假设4.26.2 中得到修复,或者至少我们是这么认为的; 实际上已在 4.26.3 中修复:https://hypothesis.readthedocs.io/en/latest/changes.html#v4-26-3

【讨论】:

  • 试一试:它似乎不适用于我的示例。我将在 github 问题中添加详细信息。
  • 感谢您关注此问题 - 事实证明,我们修复了一个屏蔽错误,并且需要 修复您的实际问题。但据我所知,它现在已经修复了!
猜你喜欢
  • 1970-01-01
  • 2018-08-14
  • 1970-01-01
  • 1970-01-01
  • 2015-12-06
  • 2013-06-10
  • 1970-01-01
  • 2022-11-26
  • 1970-01-01
相关资源
最近更新 更多