固定装置的pytest夹具

Toc*_*Toc 6 python pytest

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

文件test_for_class_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):
    ...
Run Code Online (Sandbox Code Playgroud)

class_b,class_c等存在类似的文件...唯一的区别是setup_resource_1和setup_resource_2的内容.

现在我想重新使用在test_for_class_a.py,test_for_class_b.py和test_for_class_c.py中定义的fixtures setup_class_a,setup_class_b,setup_class_c来对它们进行测试.

在文件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)
    ...
Run Code Online (Sandbox Code Playgroud)

但我正在寻找一种更通用的方法:

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)
    ...
Run Code Online (Sandbox Code Playgroud)

有什么方法可以做一些接近它的事情吗?我一直在寻找工厂和抽象pytest工厂的工厂,但我正在努力与pytest定义夹具的方式.有什么方法可以解决这个问题吗?

Toc*_*Toc 2

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

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
Run Code Online (Sandbox Code Playgroud)

这隐含地依赖于以下事实:所有 test_all_fixture 在所有 test_register_class* 之后执行。它显然很脏,但它有效......