如何在pytest测试脚本外部获取已应用的pytestmark标记列表
你当前使用的pytest.mark._markers是pytest全局已注册标记的集合,并非当前运行测试的已应用标记列表,因此无法拿到预期结果。以下是符合你要求的实现方案,无需修改test_1.py的业务逻辑,也不需要使用fixture:
实现方案
只需要在项目根目录新增pytest自动加载的conftest.py配置文件,再调整module.py的内部逻辑即可。
第一步:编写conftest.py
实现两个核心能力:存储当前测试运行上下文、维持原有自定义标记的跳过逻辑
import pytest # 全局变量存储当前正在运行的测试项 current_test_item = None # 配置所有自定义跳过标记对应的触发条件,替代原有specific_case = pytest.mark.skipif写法 SKIP_CONFIG = { "specific_case": <CONDITION>, # 替换为你原来的跳过条件 "specific_case_2": <CONDITION_2>, "specific_case_3": <CONDITION_3>, # 更多自定义标记按格式添加即可 } @pytest.hookimpl(tryfirst=True) def pytest_runtest_setup(item): """测试执行前存储当前测试项上下文""" global current_test_item current_test_item = item @pytest.hookimpl(trylast=True) def pytest_runtest_teardown(item): """测试执行后清空上下文避免污染""" global current_test_item current_test_item = None @pytest.hookimpl(tryfirst=True) def pytest_collection_modifyitems(items): """给带自定义标记的用例自动添加跳过逻辑,无需修改原有测试代码""" for item in items: for mark_name, skip_condition in SKIP_CONFIG.items(): if item.get_closest_marker(mark_name) and skip_condition: item.add_marker(pytest.mark.skip(reason=f"{mark_name} 触发跳过条件"))
第二步:调整module.py的属性逻辑
保持A类的外部调用接口完全不变,仅修改value属性的内部实现:
from conftest import current_test_item class A(): @property def value(self): # 非测试运行上下文直接返回默认值 if not current_test_item: return 2 # 收集当前测试所有层级的标记(模块级、类级、用例级) all_mark_names = set() # 读取模块级pytestmark if hasattr(current_test_item.module, "pytestmark"): module_marks = current_test_item.module.pytestmark module_marks = module_marks if isinstance(module_marks, list) else [module_marks] all_mark_names.update([m.name for m in module_marks]) # 读取类级pytestmark(如果测试用例在测试类中) if current_test_item.cls and hasattr(current_test_item.cls, "pytestmark"): cls_marks = current_test_item.cls.pytestmark cls_marks = cls_marks if isinstance(cls_marks, list) else [cls_marks] all_mark_names.update([m.name for m in cls_marks]) # 读取用例自身的标记 all_mark_names.update([m.name for m in current_test_item.own_markers]) # 按标记判断返回值 if "specific_case" in all_mark_names: return 1 return 2
可选兼容方案
如果你一定要保留原有specific_case = pytest.mark.skipif(<CONDITION>)的标记定义方式,只需要在定义时给每个标记添加自定义标识参数:
specific_case = pytest.mark.skipif(<CONDITION>, reason="xxx", custom_mark="specific_case") specific_case_2 = pytest.mark.skipif(<CONDITION_2>, reason="xxx", custom_mark="specific_case_2")
然后在module.py的标记收集逻辑中补充对skipif标记的自定义参数判断即可:
# 补充到all_mark_names收集逻辑之后 for mark in current_test_item.iter_markers(name="skipif"): if "custom_mark" in mark.kwargs: all_mark_names.add(mark.kwargs["custom_mark"])
内容的提问来源于stack exchange,提问作者JaSON
相关产品推荐
相关产品推荐

