Python 夹具试验夹具

Python 夹具试验夹具,python,pytest,Python,Pytest,我目前正在为一个中等大小的库(约300个文件)编写测试。 此库中的许多类共享使用pytest编码的相同测试方案: 文件测试\u针对\u类\u a.py: import pytest @pytest.fixture() def setup_resource_1(): ... @pytest.fixture() def setup_resource_2(): ... @pytest.fixture() def setup_class_a(setup_resource_1, se

我目前正在为一个中等大小的库(约300个文件)编写测试。 此库中的许多类共享使用pytest编码的相同测试方案:

文件测试\u针对\u类\u a.py:

import pytest

@pytest.fixture()
def setup_resource_1():
    ...

@pytest.fixture()
def setup_resource_2():
    ...

@pytest.fixture()
def setup_class_a(setup_resource_1, setup_resource_2):
    ...

def test_1_for_class_a(setup_class_a):
    ...

def test_2_for_class_a(setup_class_a):
    ...
b类、c类等也有类似的文件。。。唯一的区别是设置资源1和设置资源2的内容

现在,我想重新使用test_for_class_a.py、test_for_class_b.py和test_for_class_c.py中定义的fixture setup_class_a、setup_class_b、setup_class_c.py来运行测试

在文件test_all_class.py中,此操作有效,但每次测试仅限于一个夹具:

from test_for_class_a import *

@pytest.mark.usefixtures('setup_class_a')      # Fixture was defined in test_for_class_a.py
def test_some_things_on_class_a(request)
    ...
但我正在寻找一种更一般的方法:

from test_for_class_a import *
from test_for_class_b import *   # I can make sure I have no collision here 
from test_for_class_c import *   # I can make sure I have no collision here 

==> @generate_test_for_fixture('setup_class_a', 'setup_class_b', 'setup_class_c') 
def test_some_things_on_all_classes(request)
    ...
有没有办法做到这一点? 我一直在关注工厂的工厂和抽象的pytest工厂,但我正在努力研究pytest定义夹具的方式。
有什么方法可以解决这个问题吗?

我发现的一个解决方案是滥用测试用例,如下所示:

from test_for_class_a import *
from test_for_class_b import *
from test_for_class_c import *

list_of_all_fixtures = []


# This will force pytest to generate all sub-fixture for class a
@pytest.mark.usefixtures(setup_class_a)
def test_register_class_a_fixtures(setup_class_a):
    list_of_fixtures.append(setup_class_a)


# This will force pytest to generate all sub-fixture for class b
@pytest.mark.usefixtures(setup_class_b)
def test_register_class_b_fixtures(setup_class_b):
    list_of_fixtures.append(setup_class_b)


# This will force pytest to generate all sub-fixture for class c
@pytest.mark.usefixtures(setup_class_c)
def test_register_class_b_fixtures(setup_class_c):
    list_of_fixtures.append(setup_class_c)


# This is the real test to apply on all fixtures
def test_all_fixtures():
    for my_fixture in list_of_all_fixtures:
        # do something with my_fixture

这隐式地依赖于这样一个事实,即所有test_all_fixture都是在所有test_register_类*之后执行的。它显然很脏,但它能工作…

我们在工作中遇到了同样的问题,我希望每个案例只写一次夹具。所以我写了插件
pytest data
,就是这样做的。例如:

@pytest.fixture
def resource(request):
    resource_data = get_data(reqeust, 'resource_data', {'some': 'data', 'foo': 'foo'})
    return Resource(resource_data)

@use_data(resource_data={'foo': 'bar'})
def test_1_for_class_a(resource):
    ...

@use_data(resource_data={'foo': 'baz'})
def test_2_for_class_a(resource):
    ...
最棒的是,您只需编写一次带有一些默认值的fixture。当您只需要该装置/资源,而不关心具体的设置时,您只需要使用它。当您需要测试某个特定属性时,比如说检查该资源是否也可以处理100个字符长的值,您可以通过
use\u data
decorator传递它,而不是编写另一个fixture

这样你就不必关心冲突,因为一切都只会发生一次。然后,您可以对所有装置使用
conftest.py
,而无需在测试模块中导入。例如,我们分离了所有装置的深层模块,所有装置都包含在top
conftest.py


插件
pytest数据的文档

我认为,只有
pytest\u generate\u test()
()才能给你这样的定制能力:

def pytest\u generate\u测试(metafunc):
如果metafunc.funcargnames中的“db”:
metafunc.addcall(param=“d1”)
metafunc.addcall(param=“d2”)
编辑:Ooops,回答了一个问题:我有比python更老的经验