用于定位不稳定Python测试原因的工具
摘要
pytest-leak-finder 是一个 pytest 插件,它使用二分查找来识别当一起运行时,哪个更早的测试导致后续测试失败。
查看缓存全文
缓存时间: 2026/08/03 01:29
mgaitan/pytest-leak-finder
来源: https://github.com/mgaitan/pytest-leak-finder
PyPI 版本 (https://pypi.org/project/pytest-leak-finder) Python 版本 (https://pypi.org/project/pytest-leak-finder) CI (https://github.com/mgaitan/pytest-leak-finder/actions/workflows/ci.yml)
你有一个测试,单独执行时通过,但在运行整个测试套件时却失败了。发生了什么?依我看,是某个之前的测试把环境弄脏了。但到底是哪个/哪几个呢?可能前面的测试有一大堆,对吧?
这个插件通过对目标之前的已收集测试进行二分搜索(类似于 git bisect)来帮助找出罪魁祸首。
第一次运行时,它会收集这些测试的前半部分,再加上失败的测试(即目标)。如果目标失败,说明我们走对了路,于是继续做新的二分。当目标没有失败时,它会改变下一次二分的“一半”范围。
考虑以下示例:
$ pytest -v demo/test_demo.py
collected 6 items
tests/test_demo.py::test1 PASSED
tests/test_demo.py::test2 PASSED
tests/test_demo.py::test3 PASSED
tests/test_demo.py::test4 PASSED
tests/test_demo.py::test5 FAILED
tests/test_demo.py::test6 PASSED
$ pytest -v --lf demo/test_demo.py
collected 6 items / 5 deselected / 1 selected
tests/test_demo.py::test5 PASSED
你可以使用 pytest-leak-finder 来找出有问题的测试。
第一次运行时,它会把失败的测试设为“目标”,并停止本次会话。
$ pytest -v --leak-finder demo/test_demo.py
collected 6 items
tests/test_demo.py::test1 PASSED
tests/test_demo.py::test2 PASSED
tests/test_demo.py::test3 PASSED
tests/test_demo.py::test4 PASSED
tests/test_demo.py::test5 FAILED
===================================================== Leak finder =====================================================
Target set to: pytest-leak-finder/tests/test_demo.py::test5
Next step: a
Current target is: pytest-leak-finder/tests/test_demo.py::test5
============================================= 1 failed, 4 passed in 0.13s =============================================
第二次执行将运行目标之前已通过测试的前半部分(步骤“a”,由 test1 和 test2 组成)。
如果目标仍然失败,就会继续深入这条路径并再次分割。但在这个示例中,它通过了,所以我们会丢弃这一半,并认为另一半包含了泄漏源。这就是为什么“下一步”会是“ba”。
$ pytest -v --leak-finder demo/test_demo.py
collected 6 items / 3 deselected / 3 selected
demo/test_demo.py::test1 PASSED [ 33%]
demo/test_demo.py::test2 PASSED [ 66%]
demo/test_demo.py::test5 PASSED [100%]
===================================================== Leak finder =====================================================
We reach the target and nothing failed. Let's change the last half.
Next step: ba
Current target is: pytest-leak-finder/demo/test_demo.py::test5
=========================================== 3 passed, 3 deselected in 0.03s ===========================================
因此,新的步骤将是“B-A”,即 test3。
$ pytest -v --leak-finder demo/test_demo.py
collected 6 items / 3 deselected / 3 selected
tests/test_demo.py::test3 PASSED
tests/test_demo.py::test5 FAILED
===================================================== Leak finder =====================================================
We found a leak!
Leak found in: pytest-leak-finder/demo/test_demo.py::test3
Last step was: ba
就是这样,test3 正是我们要找的问题测试!
相似文章
pytest-dev/pytest
pytest 是一个成熟的 Python 测试框架,可以轻松编写简单的测试,同时能够扩展以支持应用程序和库的复杂功能测试。
用 LLM 揪出 Python C 扩展的 bug
Daniel Diniz 借助 Claude Code 与自研插件,系统性地在 44 个 Python C 扩展项目中挖出 575+ 个 bug,其中 14 个项目已合并修复。
插件案例研究:Pluggy
一篇博客文章,探讨了Pluggy——这是一个最初源自pytest的Python库,用于构建插件系统。内容包括其工作原理以及如何将其与一个玩具级HTML转换工具配合使用。
Pyrecall 开源工具:检测 LLM 微调中的灾难性遗忘 [P]
Pyrecall 是一款新的开源工具,能够检测 LLM 微调中的灾难性遗忘,通过快照训练前后的技能分数,标记性能回退,并回滚 LoRA 适配器。该工具完全在本地运行,无需外部 API。
一个简单的运行时不变量挖掘器
本文用Python实现了一个Daikon风格的运行时不变量挖掘器,包括插桩、轨迹收集、候选不变量检查以及基于蕴含的抑制,为回归测试提供了一个近似预言。