问题 如何参数化Pytest夹具


考虑以下Pytest:

import pytest

class TimeLine(object):
    instances = [0, 1, 2]

@pytest.fixture
def timeline():
    return TimeLine()

def test_timeline(timeline):
    for instance in timeline.instances:
        assert instance % 2 == 0

if __name__ == "__main__":
    pytest.main([__file__])

考试 test_timeline 使用Pytest夹具, timeline,它本身具有属性 instances。此属性在测试中迭代,因此只有断言适用于每个时,测试才会通过 instance 在 timeline.instances

然而,我真正想要做的是生成3个测试,其中2个应该通过,其中1个将失败。我试过了

@pytest.mark.parametrize("instance", timeline.instances)
def test_timeline(timeline):
    assert instance % 2 == 0

但这导致了

AttributeError: 'function' object has no attribute 'instances'

据我了解,在Pytest中,函数'变为'它的返回值,但在测试参数化时似乎还没有发生过。如何以理想的方式设置测试?


3246
2018-02-14 14:37


起源



答案:


这实际上可以通过 间接参数化

这个例子用pytest 3.1.2做你想要的:

import pytest

class TimeLine:
    def __init__(self, instances):
        self.instances = instances

@pytest.fixture
def timeline(request):
    return TimeLine(request.param)

@pytest.mark.parametrize(
    'timeline',
    ([1, 2, 3], [2, 4, 6], [6, 8, 10]),
    indirect=True
)
def test_timeline(timeline):
    for instance in timeline.instances:
        assert instance % 2 == 0

if __name__ == "__main__":
    pytest.main([__file__])

另见 这个类似的问题


11
2018-06-15 13:02





https://bitbucket.org/pytest-dev/pytest/issues/349/using-fixtures-in-pytestmarkparametrize,似乎目前无法使用灯具 pytest.mark.parametrize


1
2018-02-14 14:45





间接参数化的使用有效,但我发现需要使用 request.param 作为一个神奇的,未命名的变量有点尴尬。

这是我用过的模式。可以说,它以不同的方式尴尬,但也许你也会喜欢它!

import pytest

class TimeLine:
    def __init__(self, instances):
        self.instances = instances


@pytest.fixture
def instances():
    return [0, 0, 0]


@pytest.fixture
def timeline(instances):
    return TimeLine(instances)


@pytest.mark.parametrize('instances', [
    [1, 2, 3], [2, 4, 5], [6, 8, 10]
])
def test_timeline(timeline):
    for instance in timeline.instances:
        assert instance % 2 == 0

timeline 夹具取决于另一个夹具 instances,其默认值为 [0,0,0],但在实际测试中,我们使用 parametrize 为...注入一系列不同的值 instances

我认为它的优点是一切都有一个好名字,而且你不需要通过它 indirect=True 旗。


0
2017-09-28 13:23





而不是间接参数化,或者我的涉及继承的hacky解决方案,你也可以只使用 params 论证 @pytest.fixture()  - 我认为这是最简单的解决方案吗?

import pytest

class TimeLine:
    def __init__(self, instances=[0, 0, 0]):
        self.instances = instances


@pytest.fixture(params=[
    [1, 2, 3], [2, 4, 5], [6, 8, 10]
])
def timeline(request):
    return TimeLine(request.param)


def test_timeline(timeline):
    for instance in timeline.instances:
        assert instance % 2 == 0

https://docs.pytest.org/en/latest/fixture.html#parametrizing-fixtures


0
2017-10-02 15:05