有什么方法可以将参数传递给pytest fixture吗?

Jas*_*man 6 python fixture pytest

我不是在讨论参数化夹具功能,它允许夹具多次运行以获得硬编码的参数.

我有很多测试遵循以下模式:

httpcode = 401  # this is different per call
message = 'some message'  # this is different per call
url = 'some url'  # this is different per call


mock_req = mock.MagicMock(spec_set=urllib2.Request)
with mock.patch('package.module.urllib2.urlopen', autospec=True) as mock_urlopen, \
     mock.patch('package.module.urllib2.Request', autospec=True) as mock_request:
    mock_request.return_value = mock_req
    mock_urlopen.side_effect = urllib2.HTTPError(url, httpcode, message, {}, None)
    connection = MyClass()
    with pytest.raises(MyException):
        connection.some_function()  # this changes
Run Code Online (Sandbox Code Playgroud)

从本质上讲,我有一个API客户端类,并包含自定义的,有意义的异常,将urllib2错误包装在特定于API的内容中.所以,我有这个模式 - 修补一些方法,并在其中一个上设置副作用.我在十几个不同的测试中使用它,唯一的区别是side_effect的部分使用的三个变量,以及我调用的MyClass()的方法.

有没有办法让这个pytest夹具并传入这些变量?

Ily*_*eev 16

您可以使用间接夹具参数化 http://pytest.org/latest/example/parametrize.html#deferring-the-setup-of-parametrized-resources

@pytest.fixture()
def your_fixture(request):
    httpcode, message, url = request.param
    mock_req = mock.MagicMock(spec_set=urllib2.Request)
    with mock.patch('package.module.urllib2.urlopen', autospec=True) as mock_urlopen, \
         mock.patch('package.module.urllib2.Request', autospec=True) as mock_request:
        mock_request.return_value = mock_req
        mock_urlopen.side_effect = urllib2.HTTPError(url, httpcode, message, {}, None)
        connection = MyClass()
        with pytest.raises(MyException):
            connection.some_function()  # this changes


@pytest.mark.parametrize('your_fixture', [
    (403, 'some message', 'some url')
], indirect=True)
def test(your_fixture):
   ...
Run Code Online (Sandbox Code Playgroud)

并且your_fixture将在测试前运行所需的参数

  • 我特别说过这不是我想要的...我不想多次创建夹具,我只想将参数传递给它。 (2认同)
  • 在我的代码中,fixture 只在测试中运行一次。事实上,我的代码和你的代码一样。区别在于传递参数的方式。如果您想在测试中生成参数,然后将它们传递给夹具 - 您的代码是唯一的方法。如果在测试中预定义了参数,那么我的代码也适合 (2认同)

Jas*_*man 6

自从发布我的问题以来,我已经对此进行了更多的研究,我能想到的最好的是:

固定装置不能以这种方式工作.只需使用常规功能,即:

def my_fixture(httpcode, message, url):
    mock_req = mock.MagicMock(spec_set=urllib2.Request)
    with mock.patch('package.module.urllib2.urlopen', autospec=True) as mock_urlopen, \
         mock.patch('package.module.urllib2.Request', autospec=True) as mock_request:
        mock_request.return_value = mock_req
        mock_urlopen.side_effect = urllib2.HTTPError(url, httpcode, message, {}, None)
        connection = MyClass()
        return (connection, mock_request, mock_urlopen)

def test_something():
    connection, mock_req, mock_urlopen = my_fixture(401, 'some message', 'some url')
    with pytest.raises(MyException):
        connection.some_function()  # this changes
Run Code Online (Sandbox Code Playgroud)