如何在pytest测试文件中对指定标记取反,排除目标控制器?
实现pytest标记取反(排除指定控制器)
要实现类似@pytest.notmark.pcm62的标记取反功能,无需手动添加所有其他控制器标记,同时不影响原有测试的执行逻辑,可以通过自定义装饰器+pytest钩子函数来实现:
步骤1:在conftest.py中添加配置
在测试目录下的conftest.py文件中写入以下代码:
import pytest class NotMark: def __getattr__(self, controller): # 当访问pytest.notmark.xxx时,返回all_except标记,参数为xxx return pytest.mark.all_except(controller) # 把NotMark实例绑定到pytest.notmark上 pytest.notmark = NotMark() def pytest_configure(config): # 注册自定义标记,避免pytest抛出未注册标记的警告 config.addinivalue_line( "markers", "all_except(controller): 仅在指定控制器之外的环境运行测试" ) def pytest_collection_modifyitems(config, items): # 获取命令行传入的标记表达式 target_mark = config.getoption("-m") or "" for test_item in items: # 检查当前测试是否有all_except标记 exclude_mark = test_item.get_closest_marker("all_except") if exclude_mark: excluded_controller = exclude_mark.args[0] # 如果命令行指定的标记正好是要排除的控制器,跳过该测试 if target_mark == excluded_controller: test_item.add_marker( pytest.mark.skip(reason=f"该测试排除在控制器 {excluded_controller} 上运行") )
步骤2:编写带排除标记的测试
在测试脚本中,直接用@pytest.notmark.pcm62装饰需要排除的测试:
import pytest # 原有测试:在所有控制器上都能被触发 @pytest.mark.pcm33 @pytest.mark.pcm21 @pytest.mark.pcm62 @pytest.mark.pcm52 @pytest.mark.pcm61 def test_something(): assert True # 新测试:排除pcm62控制器,其他控制器均可触发 @pytest.notmark.pcm62 def test_something_excluding_pcm62(): assert True
效果验证
- 运行
pytest -m pcm62:test_something会执行,test_something_excluding_pcm62被跳过 - 运行
pytest -m pcm33:两个测试都会执行 - 运行
pytest(不带标记):两个测试都会执行
这个方案完全符合需求:无需手动罗列所有允许的控制器标记,仅需指定要排除的目标;且原有测试的执行逻辑不受任何影响。
内容的提问来源于stack exchange,提问作者Kjeld Flarup
相关产品推荐
相关产品推荐

