pytest setup 或 teardown 报错,tmp_path 却没有保留下来
failed 保留策略的 tmp_path 终结逻辑只看 call 结果。调查期明确保留全部目录,关键诊断产物在清理前独立归档。
测试在 setup 或 teardown 报错,想查看 tmp_path 里的诊断文件,目录却已经被删掉。如果配置了 tmp_path_retention_policy = failed,要检查保留判断是否只看测试的 call 阶段。
pytest 9.1.1 的 tmp_path 终结逻辑读取 call 阶段结果,并把缺少 call 结果的情况默认为通过。setup 失败时往往没有 call;call 已通过、之后 teardown 才失败时,这份判断也来不及反映最终错误。因此“会话失败”不一定意味着这个测试的临时目录被保留。
调查期间明确保留所有测试目录
需要查看失败前后的文件时,可暂时调整现有 pytest.ini:
[pytest]
tmp_path_retention_policy = all
tmp_path_retention_count = 3
不要另建一份同名配置抢走项目入口。先从 pytest 启动信息确认读取了原来的配置文件;count = 3 表示按保留策略维护最近的会话目录,不是无限存档,也不是只保留三个文件。
设置为 all 会增加磁盘占用。调查完成后,按项目保留策略恢复原值,并在确认不再需要证据后处理任务自己的目录。不能因为配置已改回 failed,就认为此前保留的文件已经按业务要求归档或删除。
关键产物别只依赖临时目录寿命
日志、数据库快照或外部工具结果需要随 CI 作业长期保留时,应在资源清理前复制到项目约定的产物目录,并让上传步骤覆盖测试失败状态。setup 中资源还没创建就出错时,也要能区分“没有产物”与“产物被清理”。
--basetemp 指定的目录在后续运行开始时可能被清理,不适合拿一个长期资料目录来代替归档。单独指定一个路径,也不能证明每个 tmp_path 都会躲过自身终结逻辑。
这与fixture 终结钩子异常导致旧缓存未清空不同。本题是诊断文件保留策略,扩大 fixture scope 或改变钩子异常处理,不会自动让 failed 策略覆盖所有阶段。
复查分别覆盖 setup 错误、call 失败、teardown 错误与正常通过,检查最终状态和实际文件。pytest 9.1.1 的这条 call 阶段判断与最终会话状态不同,后续升级也应分别检查这些阶段,不能只用一次普通断言失败验证整个保留策略。


