当参数化测试使用参数化 Fixture 时,Fixture 范围无法工作。

8
我希望分享夹具(fixtures)在同一参数化测试实例之间,其中夹具本身也是参数化的。
#!/usr/bin/py.test -sv

import pytest

numbers_for_fixture = [0]

def pytest_generate_tests(metafunc):
    if "config_field" in metafunc.fixturenames:
        metafunc.parametrize("config_field", [1], scope='session')

@pytest.fixture(scope = 'session')
def fixture_1(config_field):
    numbers_for_fixture[0] += 1
    return '\tfixture_1(%s)' % numbers_for_fixture[0]

@pytest.fixture(scope = 'session')
def fixture_2():
    numbers_for_fixture[0] += 1
    return '\tfixture_2(%s)' % numbers_for_fixture[0]

def test_a(fixture_1):
    print('\ttest_a:', fixture_1)

def test_b(fixture_1):
    print('\ttest_b:', fixture_1)

@pytest.mark.parametrize('i', range(3))
def test_c(fixture_1, i):
    print('\ttest_c[%s]:' % i, fixture_1)

@pytest.mark.parametrize('i', range(3))
def test_d(fixture_2, i):
    print('\ttest_d[%s]:' % i, fixture_2)

我获取到以下输出:
platform linux -- Python 3.4.1 -- py-1.4.26 -- pytest-2.6.4 -- /usr/bin/python
collecting ... collected 8 items

test.py::test_a[1]      test_a:     fixture_1(1)
PASSED
test.py::test_b[1]      test_b:     fixture_1(1)
PASSED
test.py::test_c[1-0]    test_c[0]:  fixture_1(1)
PASSED
test.py::test_c[1-1]    test_c[1]:  fixture_1(2)
PASSED
test.py::test_c[1-2]    test_c[2]:  fixture_1(3)
PASSED
test.py::test_d[0]      test_d[0]:  fixture_2(4)
PASSED
test.py::test_d[1]      test_d[1]:  fixture_2(4)
PASSED
test.py::test_d[2]      test_d[2]:  fixture_2(4)
PASSED
test_atest_btest_c[0] 所有共享 fixture_1(1)。所有的 test_d 都共享 fixture_2(4)。问题在于,test_c 使用不同版本的 fixture_1

当作用域设置为 "module" 和 "class" 时,此问题也会发生,只有当测试和 fixture 都是参数化的时才会发生。

从 pytest 打印测试参数的方式来看,它似乎没有区分每个项目使用的不同类型的参数,因此它为每组参数创建一个 fixture,而不是为 fixture 使用的参数列表中的每个唯一子集创建一个 fixture。

这是 pytest 中的 bug 吗?还是我忽略了设置某些配置或其他内容?是否有解决方法?


似乎是一个已报告的错误 - https://bitbucket.org/hpk42/pytest/issue/634/metafuncparametrize-overwrites-scope - Idan Arye
更新链接 https://bitbucket.org/pytest-dev/pytest/issue/634/metafuncparametrize-overwrites-scope - Efren
这个问题还没有完全解决。请参考相关问题 https://github.com/pytest-dev/pytest/issues/1697 - Andriy
看一下这个问题,或许能帮到你。 - Ederson Badeca
2个回答

2
简而言之,在这种情况下,作用域被有效地忽略了。运行pytest并使用--setup-show开关以更好地查看何时设置和拆卸固件。
解决方法:
注释掉pytest_generate_tests函数,并添加以下内容:
@pytest.fixture('session', [1])
def config_field(request):
    return request.param

现在您应该看到了正确的设置和拆卸嵌套。
动态参数的解决方法:
我需要从cli参数设置我的参数,并且必须使用pytest_generate_tests。
将indirect设置为True,参数设置为cli参数。
def pytest_generate_tests(metafunc):
    if "config_field" in metafunc.fixturenames:
        metafunc.parametrize(
            "config_field",
            metafunc.config.getoption('some_option'),
            True,
            'session'
        )

添加一个占位符夹具:

@pytest.fixture('session')
def config_field(request):
    return request.param

我无法让这个动态参数的解决方法对我起作用。 - Chris J Harris

0

你可以从你的特征中返回yield,这可能会返回相同的值:

@pytest.fixture(scope = 'session')
def fixture_1(config_field):
   .. yield <fixture-properties>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接