如何访问夹具的值作为参数化测试的输入
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)
.
在 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)
.