如何在pytest的Session级Fixture中根据关联测试用例的执行结果决定是否打印资源输出
如何在pytest的Session级Fixture中根据关联测试用例的执行结果决定是否打印资源输出
我完全懂你的需求——你有个session级别的fixture,用来启动Docker容器这类会产生大量日志输出的资源,现在就想在用到这个fixture的测试用例里只要有一个失败时,才把这些资源的输出打出来;要是所有关联测试都通过,哪怕其他没用到这个fixture的测试(比如你的test_foo)失败了,也不想打印这些冗余内容,对吧?
我给你一个直接能用的实现方案,核心就是跟踪关联测试的执行结果,在fixture销毁阶段做判断:
import pytest @pytest.fixture(scope="session") def global_resource(request): # 标记:是否有使用该fixture的测试用例执行失败 has_related_failure = False # 这里模拟资源产生的输出,实际项目里替换成你的真实资源输出(比如Docker日志) resource_output = """ Docker容器启动成功,端口映射:8080->80 应用初始化日志:Loading config... 可能的错误信息:[ERROR] 某个请求超时 """ # 定义一个钩子函数,监听所有测试用例的执行报告 def track_related_test_failures(report): nonlocal has_related_failure # 只关心测试用例实际执行阶段(call阶段)的失败 if report.when == "call" and report.failed: # 通过测试的唯一ID找到对应的测试项 for test_item in request.session.items: if test_item.nodeid == report.nodeid: # 检查这个测试是否使用了当前的global_resource fixture if "global_resource" in test_item.fixturenames: has_related_failure = True break # 把这个钩子注册到pytest会话中,让它自动监听测试报告 request.session.config.hook.pytest_runtest_makereport.append(track_related_test_failures) # ------------------------------ # 在这里写你的资源启动逻辑,比如启动Docker容器 # 示例:start_docker_container() # ------------------------------ yield # 测试用例会从这里获取fixture,执行测试逻辑 # ------------------------------ # 这里是session结束时的fixture销毁阶段 # ------------------------------ if has_related_failure: print("\n" + "="*50) print("关联测试用例失败,展示资源输出:") print("="*50) print(resource_output) print("="*50 + "\n")
给你拆解下这段代码的工作逻辑:
- 我们用
has_related_failure这个变量做开关,初始是False - 注册的
track_related_test_failures钩子会盯着每个测试的执行结果:只要某个测试在实际运行阶段失败,就检查它是不是用了global_resourcefixture——如果是,就把开关拨到True - 等所有测试都跑完,fixture进入销毁阶段时,就看这个开关:如果是True(有关联测试失败),就把预先存好的资源输出打印出来;如果是False,就啥也不做
完全匹配你表格里的所有场景:
- 当bar、baz都通过时,哪怕foo失败,开关还是False,不打印
- 只要bar或baz有一个失败,开关就变成True,一定会打印资源输出
另外提个小建议:如果你的资源输出是实时产生的(比如Docker的实时日志),可以把输出临时存在内存里(比如用io.StringIO)或者临时文件里,等销毁阶段再决定是否打印,这样就不会在测试过程中提前输出干扰测试结果啦。
备注:内容来源于stack exchange,提问作者Arne
相关产品推荐
相关产品推荐

