pytest 测试变慢时,可以先看最耗时的用例

64 次浏览4 条回复

测试套件越来越慢时,可以先让 pytest 列出最耗时的 10 个阶段:

python -m pytest --durations=10

输出会区分 setup、call 和 teardown,能看出时间到底花在用例本身,还是 fixture 的准备与清理上。只想把超过 1 秒的阶段都列出来,可以再加 --durations-min=1.0。

环境:Python 3.8+、pytest 6+。最好在相同机器、相同依赖和相同测试数据下比较;这个结果适合先找嫌疑点,不等同于严谨的性能基准。

这个先定位热点很实用。要是 setup 本身占时明显,除了看 fixture 依赖,还可以临时加 --setup-show 看每个 fixture 的执行;如果主要慢在 call,再把最慢用例单独跑几次确认是否稳定。对比时最好固定并发参数,不然机器负载变化也会把排序搅乱。

Nathan03Lv1#1

这个先定位热点很实用。要是 setup 本身占时明显,除了看 fixture 依赖,还可以临时加 --setup-show 看每个 fixture 的执行;如果主要慢在 call,再把最慢用例单独跑几次确认是否稳定。对比时最好固定并发参数,不然机器负载变化也会把排序搅乱。

如果是在 CI 里长期观察,建议把 --durations=10 的结果和一次基线运行放在一起看,别只盯单次排序。fixture 变慢时还可以检查它的 scope;本来每个用例都要创建的资源,误用 function scope 会把准备时间放大。不过共享 fixture 改成更长生命周期前,也要确认测试之间不会互相污染。

阿线Lv1#2

如果是在 CI 里长期观察,建议把 --durations=10 的结果和一次基线运行放在一起看,别只盯单次排序。fixture 变慢时还可以检查它的 scope;本来每个用例都要创建的资源,误用 function scope 会把准备时间放大。不过共享 fixture 改成更长生命周期前,也要确认测试之间不会互相污染。

还有个容易漏掉的点:--durations 只告诉你耗时,不会说明这次变慢是不是偶发。可以把同一条最慢用例单独跑几次,例如 python -m pytest tests/test_api.py::test_x -q --count=5 需要额外安装 pytest-repeat;不想加插件的话就让 CI 重复执行命令并比较结果。若每次排序都不稳定,先查外部服务、磁盘和缓存状态,再调整 fixture scope,免得把环境抖动当成测试本身的问题。

如果项目用了 pytest-xdist,排查时可以先关掉并行再跑一次:python -m pytest -n 0 --durations=10。并行调度和 worker 启动会影响耗时排序,尤其是短用例很多时;先拿串行结果定位慢点,再单独评估并行后的总耗时,会更容易区分用例慢和调度开销。环境需已安装 pytest-xdist。