0

我正在尝试执行一个用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函数调用放在文件末尾,但这并没有以任何方式改变测试行为)

假设快速入门指南说调用该函数会起作用,但显然不起作用。(公平地说,文档没有指定如何使用 运行测试@composite

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

4

1 回答 1

2

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

您可以通过使用@givenand来完成您想要做的事情st.data()

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

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

于 2020-07-08T12:31:45.010 回答