【发布时间】:2020-05-24 19:34:29
【问题描述】:
Pytest 在 Python 3.7 上失败了以下测试用例,并出现“fixture 'func' not found”。在 Python 2.7 上,相同的代码成功。在这两种情况下,都使用 pytest 4.6.9:
pytest_decorator_issue/test_issue.py的内容:
import functools
def my_decorator(func):
def wrapper_func(*args, **kwargs):
# do something on entry
ret = func(*args, **kwargs)
# do something on exit
return ret
return functools.update_wrapper(wrapper_func, my_decorator)
@my_decorator
def test_bla():
# perform some test
pass
在 Python 3.7 上调用 pytest:
$ pytest pytest_decorator_issue -vv
=============== ... test session starts ...
platform darwin -- Python 3.7.5, pytest-4.6.9, py-1.8.0, pluggy-0.13.1 -- .../virtualenvs/pywbem37/bin/python
cachedir: .pytest_cache
rootdir: ...
plugins: requests-mock-1.7.0, cov-2.8.1
collected 1 item
pytest_decorator_issue/test_issue.py::test_bla ERROR [100%]
============ ... ERRORS ...
____________ ... ERROR at setup of test_bla ...
file .../pytest_decorator_issue/test_fixture_issue.py, line 3
def my_decorator(func):
E fixture 'func' not found
> available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, requests_mock, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory
> use 'pytest --fixtures [testpath]' for help on them.
.../pytest_decorator_issue/test_fixture_issue.py:3
============== ... 1 error in 0.01 seconds =================================================================
Pytest 在看到装饰器函数的参数时显然决定寻找一个名为“func”的夹具,但为什么它在 Python 2.7 上不这样做,我怎么能在 pytest 测试中拥有像这样的简单装饰器功能?
只是为了比较版本,在 Python 2,7 上,相关的 pytest 输出是:
platform darwin -- Python 2.7.16, pytest-4.6.9, py-1.8.0, pluggy-0.13.1 -- .../virtualenvs/pywbem27/bin/python
cachedir: .pytest_cache
rootdir: ...
plugins: requests-mock-1.7.0, cov-2.8.1
collected 1 item
更新:
我刚刚发现,当使用 functools.wraps 装饰器而不是 functools.update_wrapper() 时,pytest 在 Python 2.7 和 3.7 上都很满意:
def my_decorator(func):
@functools.wraps(func)
def wrapper_func(*args, **kwargs):
# do something on entry
ret = func(*args, **kwargs)
# do something on exit
return ret
return wrapper_func
谁能解释一下?
【问题讨论】:
-
我认为您对
update_wrapper的调用中的第二个参数必须是func而不是my_decorator。不过,不确定为什么这在 Python 2 下有效。 -
非常感谢!!事实证明你就在那里。按照您的建议更正第二个参数修复了所有情况。随时重新发布您的评论作为对这个问题的回答。
标签: python pytest python-decorators