【问题标题】:How to execute Python functions using Hypothesis' composite strategy?如何使用 Hypothesis 的复合策略执行 Python 函数?
【发布时间】:2020-10-17 02:12:09
【问题描述】:

我正在尝试执行一个用 Hypothesis' @strategy.composite 装饰器装饰的函数。

我知道我可以使用 @given 装饰器测试函数,例如 -

from hypothesis import given
from hypothesis import strategies as st

@given(st.integers(min_value=1))
def test_bar(x):
    assert x > 0

pytest 使用 - pytest <filename.py>

但是对于带有 @strategy.composite 装饰器的函数,比如 -

from hypothesis import strategies as st
from hypothesis import given
import pytest

@st.composite
def test_foo(draw):
    arg1 = draw(st.integers(min_value=1))
    arg2 = draw(st.lists(st.integers(), min_size=arg1, max_size=arg1))
    print(arg1, " ", arg2)
    assert(len(arg2) == arg1)

我无法以类似的方式执行测试。
使用 pytest 时,我无法执行测试(使用 python 执行 python 文件什么都不做)-

[reik@reik-msi tests]$ pytest testhypo.py
==================================== test session starts ====================================
platform linux -- Python 3.8.3, pytest-5.4.3, py-1.8.1, pluggy-0.13.1
rootdir: /home/reik/tests
plugins: hypothesis-5.16.0, lazy-fixture-0.6.3
collected 1 item                                                                            

testhypo.py F                                                                         [100%]

========================================= FAILURES ==========================================
_________________________________________ test_foo __________________________________________

item = <Function test_foo>

    @pytest.hookimpl(hookwrapper=True)
    def pytest_runtest_call(item):
        if not hasattr(item, "obj"):
            yield
        elif not is_hypothesis_test(item.obj):
            # If @given was not applied, check whether other hypothesis
            # decorators were applied, and raise an error if they were.
            if getattr(item.obj, "is_hypothesis_strategy_function", False):
>               raise InvalidArgument(
                    "%s is a function that returns a Hypothesis strategy, but pytest "
                    "has collected it as a test function.  This is useless as the "
                    "function body will never be executed.  To define a test "
                    "function, use @given instead of @composite." % (item.nodeid,)
                )
E               hypothesis.errors.InvalidArgument: testhypo.py::test_foo is a function that returns a Hypothesis strategy, but pytest has collected it as a test function.  This is useless as the function body will never be executed.  To define a test function, use @given instead of @composite.

/usr/lib/python3.8/site-packages/hypothesis/extra/pytestplugin.py:132: InvalidArgument
================================== short test summary info ==================================
FAILED testhypo.py::test_foo - hypothesis.errors.InvalidArgument: testhypo.py::test_foo is...
===================================== 1 failed in 0.06s =====================================

我尝试添加函数调用test_foo(),但我得到了同样的错误。

然后我尝试在函数上方添加@given 并得到不同的错误 -

========================================== ERRORS ===========================================
________________________________ ERROR at setup of test_foo _________________________________
file /usr/lib/python3.8/site-packages/hypothesis/core.py, line 903
      def run_test_as_given(test):
E       fixture 'test' not found
>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, monkeypatch, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory
>       use 'pytest --fixtures [testpath]' for help on them.

/usr/lib/python3.8/site-packages/hypothesis/core.py:903
================================== short test summary info ==================================
ERROR testhypo.py::test_foo

如果我这样做 @given() - 请注意额外的大括号,相反,我会收到另一个错误 -

========================================= FAILURES ==========================================
_________________________________________ test_foo __________________________________________

arguments = (), kwargs = {}

    def wrapped_test(*arguments, **kwargs):
>       raise InvalidArgument(message)
E       hypothesis.errors.InvalidArgument: given must be called with at least one argument

/usr/lib/python3.8/site-packages/hypothesis/core.py:234: InvalidArgument
================================== short test summary info ==================================
FAILED testhypo.py::test_foo - hypothesis.errors.InvalidArgument: given must be called wit...

我尝试将代码包装在另一个函数中 -

from hypothesis import strategies as st
from hypothesis import given
import pytest

def demo():
    @st.composite
    def test_foo(draw):
        arg1 = draw(st.integers(min_value=1))
        arg2 = draw(st.lists(st.integers(), min_size=arg1, max_size=arg1))
        print(arg1, " ", arg2)
        assert(len(arg2) == arg1)

但这也没用 -

[reik@reik-msi tests]$ python testhypo.py
[reik@reik-msi tests]$ pytest testhypo.py
==================================== test session starts ====================================
platform linux -- Python 3.8.3, pytest-5.4.3, py-1.8.1, pluggy-0.13.1
rootdir: /home/reik/tests
plugins: hypothesis-5.16.0, lazy-fixture-0.6.3
collected 0 items                                                                           

=================================== no tests ran in 0.00s ===================================

(我也尝试将demo 函数调用放在文件末尾,但这并没有以任何方式改变测试行为)

Hypothesis quick start guide 表示调用该函数可以工作,但显然不行。 (公平地说,文档没有说明如何使用@composite 运行测试)

如何测试用@strategy.composite 修饰的函数?我没有使用 pytest - 我宁愿不必实际使用它,但它似乎是测试功能的最简单方法(用@given 装饰)所以我决定去路线。

【问题讨论】:

    标签: python pytest python-hypothesis property-based-testing


    【解决方案1】:

    @st.composite 是一个帮助函数,用于定义自定义策略,而不是测试。

    使用@givenst.data() 可以完成您想要做的事情:

    @given(st.data())
    def test_foo(data):
        x = data.draw(st.integers())
        ...
    

    https://hillelwayne.com/post/property-testing-complex-inputs/ 很好地概述了如何使用这些技术。

    【讨论】:

      猜你喜欢
      • 2021-04-26
      • 2018-03-03
      • 2017-07-22
      • 1970-01-01
      • 1970-01-01
      • 2012-12-22
      • 2019-08-03
      • 2017-07-16
      • 2021-10-26
      相关资源
      最近更新 更多