首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >夹具中最热的夹具

夹具中最热的夹具
EN

Stack Overflow用户
提问于 2016-03-04 00:35:59
回答 3查看 8.3K关注 0票数 10

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

文件test_for_class_a.py:

代码语言:javascript
复制
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):
    ...

类似的文件也存在于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中,这是可行的,但它被限制为每个测试只能有一个fixture:

代码语言:javascript
复制
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)
    ...

但我正在寻找一种方法来执行更一般的操作:

代码语言:javascript
复制
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定义fixture的方式。有没有办法解决这个问题?

EN

回答 3

Stack Overflow用户

发布于 2016-06-02 03:10:37

我们在工作中遇到了同样的问题,我希望为每个案例只编写一次fixture。所以我写了一个插件pytest-data来做这件事。示例:

代码语言:javascript
复制
@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。当你只需要那个fixture/资源,而不关心具体的设置时,你可以直接使用它。当您需要测试某些特定属性时,假设要检查该资源是否也可以处理100个字符长值,您可以通过use_data装饰器传递它,而不是编写另一个fixture。

有了它,你就不必关心冲突了,因为所有的东西只会出现一次。然后,您可以对所有的fixture使用conftest.py,而无需在测试模块中导入。例如,我们分离了所有fixtures的深层模块,并且都包含在顶级conftest.py中。

插件pytest-data文档:http://horejsek.github.io/python-pytest-data/

票数 3
EN

Stack Overflow用户

发布于 2016-03-04 18:58:41

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

代码语言:javascript
复制
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_class*之后执行的。它显然是相当脏,但它是有效的。

票数 1
EN

Stack Overflow用户

发布于 2021-03-14 07:08:22

我认为,只有pytest_generate_test() (example)才能提供这样的定制化能力:

代码语言:javascript
复制
def pytest_generate_tests(metafunc):
    if 'db' in metafunc.funcargnames:
        metafunc.addcall(param="d1")
        metafunc.addcall(param="d2")

编辑:哦,回答了比python更老的我有o.O经验的问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35777854

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档