如何从pytest_runtest_makereport钩子识别xfailed或xpassed测试结果?
在
pytest_runtest_makereport钩子中精准识别xfailed/xpassed的实现方案 此前观察到的“xfailed、xpassed被统一标记为skipped”现象,本质是仅依赖report.outcome单一字段做判断导致的分类偏差。pytest内置的xfail插件在生成测试报告时,会将非严格模式下的xfailed、xpassed类用例的outcome统一设置为skipped,但报告对象本身挂载了可精准识别分类的专属属性,所有分类需要的字段在pytest_runtest_makereport触发时就已完整写入,完全不需要等到pytest_terminal_summary阶段再匹配nodeid列表。
核心判定规则
直接从钩子返回的TestReport对象上提取属性做分类即可,逻辑与pytest内置终端统计的分类逻辑完全同源:
- 识别xfailed:报告触发阶段为测试用例实际执行的
call阶段,报告对象存在非空wasxfail属性(由xfail插件挂载,记录预期失败的标记原因),且用例执行未出现非预期通过结果。 - 识别xpassed:报告触发阶段为
call阶段,存在非空wasxfail属性,且报告对象的passed值为True——对应标记了预期失败、实际执行通过的用例场景。 - 识别普通skipped:报告任意触发阶段不存在
wasxfail属性,且outcome为skipped,对应@pytest.mark.skip、条件不满足触发常规跳过的场景。
可直接运行的钩子实现
def pytest_runtest_makereport(item, call): # 仅处理用例真正执行的call阶段,过滤setup/teardown阶段的报告干扰 if call.when != "call": return report = call.report result_category = None # 优先判断xfail关联场景 has_xfail_mark = bool(getattr(report, "wasxfail", "")) if has_xfail_mark: result_category = "xpassed" if report.passed else "xfailed" else: # 处理非xfail的常规测试结果 if report.passed: result_category = "passed" elif report.failed: result_category = "failed" elif report.skipped: result_category = "skipped" # 此处可直接推送近实时测试指标,无需等待全量测试流程结束 print(f"实时上报测试结果: 用例{item.nodeid} -> 分类{result_category}")
注意事项
- 上述分类结果与pytest终端统计中
terminalreporter.stats的分类结果完全一致,不存在偏差,不需要额外维护xfailed、xpassed的nodeid列表做二次匹配。 - 必须过滤setup、teardown阶段的报告内容,否则会把环境初始化阶段触发的跳过,误判为用例执行完成的结果,影响指标准确性。
内容的提问来源于stack exchange,提问作者Loren
相关产品推荐
相关产品推荐

