pytest 测试变慢时,可以先看 --durations

77 次浏览7 条回复

测试套件突然变慢,不一定要先上 profiler。pytest 可以直接列出最慢的用例:

pytest --durations=10

它会在结尾显示耗时最长的 10 个测试;想把很短的测试也列出来,可以用 --durations=0 看完整列表。

环境:pytest 4.2+。这个参数只统计本次运行,先确认测试选择范围和并行配置一致,再根据结果决定是拆 fixture、减少重复 IO,还是单独处理慢用例。

这个参数很适合做第一轮定位。再补一个容易忽略的点:想把短耗时条目也纳入统计,可以用 pytest --durations=0 --durations-min=0。输出里如果出现 setup/teardown,慢点可能在 fixture,不一定是测试函数本身。用了 xdist 的话,我一般会先单进程跑一遍,方便比较各项耗时。

别熬夜啦Lv1#1

这个参数很适合做第一轮定位。再补一个容易忽略的点:想把短耗时条目也纳入统计,可以用 pytest --durations=0 --durations-min=0。输出里如果出现 setup/teardown,慢点可能在 fixture,不一定是测试函数本身。用了 xdist 的话,我一般会先单进程跑一遍,方便比较各项耗时。

如果 durations 里出现 setup/teardown 还不够直观,可以临时加 --setup-show 看 fixture 的执行层级;不过输出会比较吵,定位完就去掉。参数化用例也会拆成多条,比较前最好先固定测试选择范围。

MukiLv1#2

如果 durations 里出现 setup/teardown 还不够直观,可以临时加 --setup-show 看 fixture 的执行层级;不过输出会比较吵,定位完就去掉。参数化用例也会拆成多条,比较前最好先固定测试选择范围。

如果是在 CI 里排查偶发变慢,可以把 pytest --durations=20 -q 的末尾输出作为构建日志或 artifact 留下来,再和正常运行对比。别直接拿不同的测试选择范围比较;参数化用例数量、是否启用 xdist 都会让耗时排名失真。

Ryan小满Lv1#3

如果是在 CI 里排查偶发变慢,可以把 pytest --durations=20 -q 的末尾输出作为构建日志或 artifact 留下来,再和正常运行对比。别直接拿不同的测试选择范围比较;参数化用例数量、是否启用 xdist 都会让耗时排名失真。

如果只是想盯住明显偏慢的用例,可以加个阈值,比如 pytest --durations=10 --durations-min=1.0,这样短用例不会把输出挤满。阈值最好和 CI 的正常基线一起调,别把偶发的机器抖动当成回归。

还有一种情况是收集阶段变慢,--durations 不一定能看出来,尤其是模块导入或动态生成用例比较重时。可以单独跑 time pytest --collect-only -q 看收集耗时,再和正常执行时间分开判断。

Nathan03Lv1#5

还有一种情况是收集阶段变慢,--durations 不一定能看出来,尤其是模块导入或动态生成用例比较重时。可以单独跑 time pytest --collect-only -q 看收集耗时,再和正常执行时间分开判断。

这个区分很关键。要是 collect-only 已经慢,优先查 conftest.py 导入、插件和动态收集;收集正常、执行阶段才慢,再看 fixture 或具体用例。CI 里把两段耗时分开记,别只看总 wall time 就归因到测试本身。

ZiorLv1#6

这个区分很关键。要是 collect-only 已经慢,优先查 conftest.py 导入、插件和动态收集;收集正常、执行阶段才慢,再看 fixture 或具体用例。CI 里把两段耗时分开记,别只看总 wall time 就归因到测试本身。

还有个容易误判的点:--durations 看的是墙钟时间,不等于 CPU 真正在跑。像网络、文件 IO 或锁等待偏多的用例,排名靠前不一定适合直接优化代码。可以先固定同一批测试、连续跑几次,看耗时是否稳定;波动很大时,先查外部依赖和测试隔离,通常比盯着单个函数更快。