重命名 pytest.mark.parametrize 中的参数
Renaming parameters in pytest.mark.parametrize
我有一个代码使用目录中的文件作为参数:
def get_testcases(directory):
files = list(os.listdir(directory))
testcases = filter(lambda x: x.endswith('.yaml'), files)
for testcase in testcases:
postconf = testcase.replace('.yaml', '.conf')
yield (
os.path.join(directory, testcase),
os.path.join(directory, postconf)
)
def get_pre_configs(directory):
for file in os.listdir(directory):
if file.endswith('.conf'):
yield os.path.join(directory, file)
@pytest.mark.parametrize("pre_config", get_pre_configs('pre_configs'))
@pytest.mark.parametrize("testcase_declaration, testcase_result", get_testcases('testcases'))
def test_foo(pre_config, testcase_declaration, testcase_result):
assert testcase_declaration
assert testcase_result
assert pre_config
它按我的需要工作,但我不喜欢 pytest 输出:
test_interface.py::test_foo[testcases/up.yaml-testcases/up.conf-pre_configs/bad.conf] PASSED [ 16%]
test_interface.py::test_foo[testcases/up.yaml-testcases/up.conf-pre_configs/simple.conf] PASSED [ 33%]
test_interface.py::test_foo[testcases/up.yaml-testcases/up.conf-pre_configs/complicated.conf] PASSED [ 50%]
test_interface.py::test_foo[testcases/down.yaml-testcases/down.conf-pre_configs/bad.conf] PASSED [ 66%]
test_interface.py::test_foo[testcases/down.yaml-testcases/down.conf-pre_configs/simple.conf] PASSED [ 83%]
test_interface.py::test_foo[testcases/down.yaml-testcases/down.conf-pre_configs/complicated.conf] PASSED [100%]
有什么方法可以显示与传递给测试的值不同的测试名称?我想 trim 去掉目录名和文件名的扩展名(仅用于测试名称,我想将它们 'as is' 传递给测试)。
原来@pytest.mark.parametrize
(还有@pytest.fixtures
)都挺厉害的。它们允许您通过指定 ids
列表来更改每个测试的名称。诀窍是动态生成 parametrize
的参数。
我重构了您的代码(详见下文)。给定包含以下内容的本地目录:
$ find . -type f -name '*.yaml' -o -name '*.conf'
./pre_configs/yikes.conf
./pre_configs/foobar.conf
./testcases/hello.yaml
./testcases/world.yaml
那么pytest的输出是:
collecting ... collected 4 items
test_foo.py::test_foo[yikes-hello] PASSED [ 25%]
test_foo.py::test_foo[yikes-world] PASSED [ 50%]
test_foo.py::test_foo[foobar-hello] PASSED [ 75%]
test_foo.py::test_foo[foobar-world] PASSED [100%]
============================== 4 passed in 0.19s ===============================
这是重构后的代码。请注意 get_testcases()
和 get_pre_configs()
如何都 return 一个 dict
可以用作 @pytest.mark.parametrize
的 kwargs
。特别是,ids
允许您覆盖 pytest
.
使用的名称
def getfiles(directory, ext):
"""return two lists: fullpath and names (without extension)"""
n = len(ext)
paths, names = zip(*[
(ent.path, ent.name[:-n])
for ent in os.scandir(directory)
if ent.is_file() and ent.name.endswith(ext)])
return paths, names
def get_testcases(directory):
ypaths, names = getfiles(directory, '.yaml')
cpaths = [f'{os.path.splitext(s)[0]}.conf' for s in ypaths]
return {
'argnames': ['testcase_declaration', 'testcase_result'],
'argvalues': zip(ypaths, cpaths),
'ids': names}
def get_pre_configs(directory):
paths, names = getfiles(directory, '.conf')
return {
'argnames': ['pre_config'],
'argvalues': zip(paths), # always wants a list of tuples
'ids': names}
@pytest.mark.parametrize(**get_pre_configs('pre_configs'))
@pytest.mark.parametrize(**get_testcases('testcases'))
def test_foo(pre_config, testcase_declaration, testcase_result):
assert os.path.isfile(pre_config)
assert os.path.isfile(testcase_declaration)
assert testcase_result
我有一个代码使用目录中的文件作为参数:
def get_testcases(directory):
files = list(os.listdir(directory))
testcases = filter(lambda x: x.endswith('.yaml'), files)
for testcase in testcases:
postconf = testcase.replace('.yaml', '.conf')
yield (
os.path.join(directory, testcase),
os.path.join(directory, postconf)
)
def get_pre_configs(directory):
for file in os.listdir(directory):
if file.endswith('.conf'):
yield os.path.join(directory, file)
@pytest.mark.parametrize("pre_config", get_pre_configs('pre_configs'))
@pytest.mark.parametrize("testcase_declaration, testcase_result", get_testcases('testcases'))
def test_foo(pre_config, testcase_declaration, testcase_result):
assert testcase_declaration
assert testcase_result
assert pre_config
它按我的需要工作,但我不喜欢 pytest 输出:
test_interface.py::test_foo[testcases/up.yaml-testcases/up.conf-pre_configs/bad.conf] PASSED [ 16%]
test_interface.py::test_foo[testcases/up.yaml-testcases/up.conf-pre_configs/simple.conf] PASSED [ 33%]
test_interface.py::test_foo[testcases/up.yaml-testcases/up.conf-pre_configs/complicated.conf] PASSED [ 50%]
test_interface.py::test_foo[testcases/down.yaml-testcases/down.conf-pre_configs/bad.conf] PASSED [ 66%]
test_interface.py::test_foo[testcases/down.yaml-testcases/down.conf-pre_configs/simple.conf] PASSED [ 83%]
test_interface.py::test_foo[testcases/down.yaml-testcases/down.conf-pre_configs/complicated.conf] PASSED [100%]
有什么方法可以显示与传递给测试的值不同的测试名称?我想 trim 去掉目录名和文件名的扩展名(仅用于测试名称,我想将它们 'as is' 传递给测试)。
原来@pytest.mark.parametrize
(还有@pytest.fixtures
)都挺厉害的。它们允许您通过指定 ids
列表来更改每个测试的名称。诀窍是动态生成 parametrize
的参数。
我重构了您的代码(详见下文)。给定包含以下内容的本地目录:
$ find . -type f -name '*.yaml' -o -name '*.conf'
./pre_configs/yikes.conf
./pre_configs/foobar.conf
./testcases/hello.yaml
./testcases/world.yaml
那么pytest的输出是:
collecting ... collected 4 items
test_foo.py::test_foo[yikes-hello] PASSED [ 25%]
test_foo.py::test_foo[yikes-world] PASSED [ 50%]
test_foo.py::test_foo[foobar-hello] PASSED [ 75%]
test_foo.py::test_foo[foobar-world] PASSED [100%]
============================== 4 passed in 0.19s ===============================
这是重构后的代码。请注意 get_testcases()
和 get_pre_configs()
如何都 return 一个 dict
可以用作 @pytest.mark.parametrize
的 kwargs
。特别是,ids
允许您覆盖 pytest
.
def getfiles(directory, ext):
"""return two lists: fullpath and names (without extension)"""
n = len(ext)
paths, names = zip(*[
(ent.path, ent.name[:-n])
for ent in os.scandir(directory)
if ent.is_file() and ent.name.endswith(ext)])
return paths, names
def get_testcases(directory):
ypaths, names = getfiles(directory, '.yaml')
cpaths = [f'{os.path.splitext(s)[0]}.conf' for s in ypaths]
return {
'argnames': ['testcase_declaration', 'testcase_result'],
'argvalues': zip(ypaths, cpaths),
'ids': names}
def get_pre_configs(directory):
paths, names = getfiles(directory, '.conf')
return {
'argnames': ['pre_config'],
'argvalues': zip(paths), # always wants a list of tuples
'ids': names}
@pytest.mark.parametrize(**get_pre_configs('pre_configs'))
@pytest.mark.parametrize(**get_testcases('testcases'))
def test_foo(pre_config, testcase_declaration, testcase_result):
assert os.path.isfile(pre_config)
assert os.path.isfile(testcase_declaration)
assert testcase_result