为什么pytest_generate_tests钩子会出现“找不到fixture”的错误,而它明明定义了fixture?

2 投票
1 回答
6127 浏览
提问于 2025-04-29 12:14

我想通过pytest_generate_tests来使用外部数据(参数)实现以下功能。这个例子可以正常工作:

@pytest.mark.parametrize('case', [1,2,3,4])
def test_regression(case):
    print case
    assert True

假设我通过命令行参数获取测试数据。所以,我创建了一个conftest.py文件,添加了一个选项--data,添加了一个fixture叫data,并且添加了pytest_generate_tests这个钩子。请注意,如果我不声明data这个fixture,这个功能就无法正常工作(但在这个例子中没有fixture的声明):http://pytest.org/latest/example/parametrize.html#generating-parameters-combinations-depending-on-command-line

import pytest

def pytest_addoption(parser):
    parser.addoption('--data', action='store', default='', help='Specify testing data')

@pytest.fixture
def data(request):
    return request.config.getoption('--data')

def pytest_generate_tests(metafunc):
    if 'data' in metafunc.funcargnames:
        # imagine data.cases = [1,2,3,4,5]
        metafunc.parametrize('case', [1,2,3,4,5]) 

例如,我有一个参数data,它包含了一些测试数据和测试用例。所以,我在conftest.py中这样定义:

# conftest.py
import pytest

def pytest_addoption(parser):
    parser.addoption('--data', action='store', default='', help='Specify testing data')

@pytest.fixture
def data(request):
    return request.config.getoption('--data')

def pytest_generate_tests(metafunc):
    if 'data' in metafunc.fixturenames:
        # lets imagine data.cases = [1,2,3,4,5]
        metafunc.parametrize('case', [1,2,3,4,5])    

# test.py (just removed @pytest.mark.parametrize line)
def test_regression(case):
    print case
    assert True

上面的例子会报错:找不到fixture 'case'。但是如果我把case换成data,它就能正常工作:

# conftest.py
import pytest

def pytest_addoption(parser):
    parser.addoption('--data', action='store', default='', help='Specify testing data')

@pytest.fixture
def data(request):
    return request.config.getoption('--data')

def pytest_generate_tests(metafunc):
    if 'data' in metafunc.fixturenames:
        # lets imagine data.cases = [1,2,3,4,5]
        metafunc.parametrize('data', [1,2,3,4,5])    

# test.py (just removed @pytest.mark.parametrize line)
def test_regression(data):
    print case
    assert True

但我需要一个名为case的测试参数。我哪里做错了呢?

暂无标签

1 个回答

5

我今天遇到了差不多一样的问题:

我不能告诉你具体的根本原因,但问题似乎是传给测试函数的参数应该是一个“固定装置”(fixture)。所以如果你用的是 data,那就没问题,因为它就像是一个固定装置。

但是如果你用的是 case,就找不到对应的固定装置了。

我通过以下方式解决了这个问题:

def pytest_generate_tests(metafunc):
    if 'func' in metafunc.fixturenames:
        # do some stuff
        metafunc.parametrize('func', all_combinations)

def test_function_prototypes(func):
    assert func

这样做会出现 fixture 'func' not found 的错误。我通过添加以下几行代码解决了这个问题:

@pytest.fixture
def func(request):
    return request.param  # pass the param to the test function

我在文档中没有找到关于需要提供这个函数的说明。

我还注意到,重新取消注释这个固定装置后,代码仍然可以正常工作。我猜这可能和缓存有关……

撰写回答