如何通过自定义装饰器提供非夹具 pytest 参数?

How can I provide a non-fixture pytest parameter via a custom decorator?

我们通过 Pytest 进行了单元测试 运行,它使用自定义装饰器在每次测试之前启动上下文管理的模拟回显服务器,并将其地址作为额外参数提供给测试。这适用于 Python 2.

但是,如果我们在 Python 3 上尝试 运行 它们,那么 Pytest 会抱怨它无法找到与额外参数名称匹配的夹具,并且测试会失败。

我们的测试看起来与此类似:

@with_mock_url('?status=404&content=test&content-type=csv')
def test_file_not_found(self, url):
    res_id = self._test_resource(url)['id']
    result = update_resource(None, res_id)
    assert not result, result
    self.assert_archival_error('Server reported status error: 404 Not Found', res_id)

像这样的装饰函数:

from functools import wraps

def with_mock_url(url=''):
    """
    Start a MockEchoTestServer and call the decorated function with the server's address prepended to ``url``.
    """
    def decorator(func):
        @wraps(func)
        def decorated(*args, **kwargs):
             with MockEchoTestServer().serve() as serveraddr:
                 return func(*(args + ('%s/%s' % (serveraddr, url),)), **kwargs)
        return decorated
    return decorator

在 Python 2 这有效;模拟服务器启动,测试得到一个类似于“http://localhost:1234/?status=404&content=test&content-type=csv”的URL,然后模拟关闭。

但是,在 Python 3 上,我们得到一个错误,“找不到夹具 'url'”。

有没有办法告诉 Python,“这个参数是从别处提供的,不需要夹具”?或者,也许有一种简单的方法可以将它变成固定装置?

您可以使用 url 作为 args 参数

@with_mock_url('?status=404&content=test&content-type=csv')
def test_file_not_found(self, *url):
    url[0] # the test url

如果我为注入的参数添加默认值以使其成为非强制性的,那么 Pytest 似乎愿意忽略它:

@with_mock_url('?status=404&content=test&content-type=csv')
def test_file_not_found(self, url=None):

装饰器然后可以按预期注入值。