如何访问夹具的值作为参数化测试的输入

How to access fixture's values as input to parametrized test

py.test 中,我需要动态定义测试,这取决于我在文件中定义的测试。

所以我在想的是在 conftest.py 中定义一个夹具来读取文件和 return 一个包含测试的字典。

文件tests.json:

{
    "test1": "text",
    "test2": "42",
    "test3": 1
}

然后我在 conftest.py 中定义一个夹具到 return 带有测试的字典:

def pytest_addoption(parser):
    parser.addoption(
        "--tests",
        default="tests.json",
    )

@pytest.fixture
def mytests(request):
    testfile = request.config.getoption("--tests")
    with open(testfile) as f:
        tests = json.load(f)
    return tests

然后我可以在 test_pytest.py 中使用如下参数化测试:

@pytest.mark.parametrize("test_name", [(key) for key, value in mytests.items()])
def test1(test_name):
    print(test_name)

这不起作用,因为在这一点上,py.test 似乎 'know' 认为 mytests 不是固定装置。我得到一个错误

E   NameError: name 'mytests' is not defined

如何正确处理?我只想能够 运行 json 文件中定义的所有测试,或者能够 select 使用 -k 从中进行单个测试如果 py.test.

选项

怎么做?


根据下面给出的一些评论,我尝试实现如下内容:

@pytest.hookimpl
def pytest_generate_tests(metafunc):
    if "myparam" in metafunc.fixturenames:
        with open(metafunc.config.option.tests) as f:
            tests = json.load(f)

        # add parametrization for each fixture name
        for name, value in tests.items():
            print(name, value)
            metafunc.parametrize("mparam", (name, value))

def test1(myparam):
    print(myparam)

但是我得到了一个错误

ERROR test_pytest.py - ValueError: duplicate 'myparam'

如评论中所述,您不能在 mark.parametrize 中使用夹具。夹具只能用于测试功能和其他夹具。

要像本例那样进行动态参数化,您可以实现挂钩函数 pytest_generate_tests:

@pytest.hookimpl
def pytest_generate_tests(metafunc):
    if "test_name" in metafunc.fixturenames:
        testfile = metafunc.config.getoption("--tests")
        with open(testfile) as f:
            tests = json.load(f)
        metafunc.parametrize("test_name", tests.items())


def test1(test_name):
    print(test_name)

这将使用配置文件中的项目对所有带有“test_name”参数(例如夹具)的测试进行参数化。

运行 使用给定的 json 文件将导致如下结果:

$ python -m pytest -s
...
collected 3 items

test_pytest.py ('test1', 'text')
.('test2', '42')
.('test3', 1)
.