我使用 pytest_generate_tests 挂钩使用外部 YAML 文件中定义的变量对 pytest 测试进行参数化。变量文件的名称在 pytest 命令行上指定(--params_file)。只有模块内的某些测试函数被参数化,并且需要此文件中的变量。因此,定义变量的命令行选项是一个可选参数。如果从命令行中省略了可选参数,那么我希望 pytest 只是“跳过”那些需要外部参数化变量的测试函数,而只运行未参数化的“其他”测试。问题是,如果省略命令行选项,pytest 将跳过所有测试函数,而不仅仅是需要参数的测试函数。
这是测试模块文件:
def test_network_validate_1(logger, device_connections,):
### Test code omitted.....
def test_lsp_throttle_timers(params_file, logger, device_connections):
### Test code omitted.....
def test_network_validate_2(logger, device_connections,):
### Test code omitted.....
Run Code Online (Sandbox Code Playgroud)
conftest.py 中的 pytest_generate_tests 挂钩:
# Note, I tried scope at function level as well but that did not help
@pytest.fixture(scope='session')
def params_file(request):
pass
def pytest_generate_tests(metafunc):
### Get Pytest rootdir
rootdir = metafunc.config.rootdir
print(f"*********** Test Function: {metafunc.function.__name__}")
if "params_file" in metafunc.fixturenames:
print("*********** Hello Silver ****************")
if metafunc.config.getoption("--params_file"):
#################################################################
# Params file now located as a separate command line argument for
# greater flexibility
#################################################################
params_file = metafunc.config.getoption("--params_file")
params_doc = dnet_generic.open_yaml_file(Path(rootdir, params_file),
loader_type=yaml.Loader)
test_module = metafunc.module.__name__
test_function = metafunc.function.__name__
names,values = dnet_generic.get_test_parameters(test_module,
test_function,
params_doc,)
metafunc.parametrize(names, values )
else:
pytest.skip("This test requires the params_file argument")
Run Code Online (Sandbox Code Playgroud)
当 params_file 选项存在时,一切正常:
pytest isis/test_isis_lsp_throttle.py --testinfo topoA_r28.yml --ulog -s --params_file common/topoA_params.yml --collect-only
===================================================================================== test session starts =====================================================================================
platform linux -- Python 3.7.4, pytest-3.7.0, py-1.8.0, pluggy-0.13.0
rootdir: /home/as2863/pythonProjects/p1-automation, inifile: pytest.ini
plugins: csv-2.0.1, check-0.3.5, pylama-7.6.6, dependency-0.4.0, instafail-0.4.0, ordering-0.6, repeat-0.7.0, reportportal-5.0.3
collecting 0 items *********** Test Function: test_network_validate_1
*********** Test Function: test_lsp_throttle_timers
*********** Test Function: test_network_validate_2
collected 3 items
<Package '/home/as2863/pythonProjects/p1-automation/isis'>
<Module 'test_isis_lsp_throttle.py'>
<Function 'test_network_validate_1'>
<Function 'test_lsp_throttle_timers'>
<Function 'test_network_validate_2'>
================================================================================ no tests ran in 0.02 seconds =================================================================================
Run Code Online (Sandbox Code Playgroud)
当省略 params_file 选项时,您可以看到没有运行任何测试,并且打印语句显示它甚至没有尝试在“test_network_validate_2”上运行 pytest_generate_tests
pytest isis/test_isis_lsp_throttle.py --testinfo topoA_r28.yml --ulog -s --collect-only ===================================================================================== test session starts =====================================================================================
platform linux -- Python 3.7.4, pytest-3.7.0, py-1.8.0, pluggy-0.13.0
rootdir: /home/as2863/pythonProjects/p1-automation, inifile: pytest.ini
plugins: csv-2.0.1, check-0.3.5, pylama-7.6.6, dependency-0.4.0, instafail-0.4.0, ordering-0.6, repeat-0.7.0, reportportal-5.0.3
collecting 0 items
*********** Test Function: test_network_validate_1
*********** Test Function: test_lsp_throttle_timers
*********** Hello Silver ****************
collected 0 items / 1 skipped
================================================================================== 1 skipped in 0.11 seconds ==================================================================================
Run Code Online (Sandbox Code Playgroud)
正如评论中的讨论所示,您不能使用pytest.skipin pytest_generate_tests,因为它将在模块范围内工作。要跳过具体测试,您可以执行以下操作:
@pytest.fixture
def skip_test():
pytest.skip('Some reason')
def pytest_generate_tests(metafunc):
if "params_file" in metafunc.fixturenames:
if metafunc.config.getoption("--params_file"):
...
metafunc.parametrize(names, values )
else:
metafunc.fixturenames.insert(0, 'skip_test')
Run Code Online (Sandbox Code Playgroud)
例如,您引入一个将跳过具体测试的夹具,并将该夹具添加到测试中。确保将其作为第一个夹具插入,这样就不会执行其他夹具。