测试套件越来越慢时,可以先让 pytest 把耗时靠前的用例列出来:
python -m pytest --durations=10
只想看超过 0.5 秒的:
python -m pytest --durations=10 --durations-min=0.5
环境:Python 3.9+、pytest 7+,在项目虚拟环境里执行。它只统计本次运行的耗时,不等于完整性能基准;如果测试本身受网络或机器负载影响,先把这些依赖隔离,不然排序会飘。
这个很适合先做第一轮定位。补一个小点:如果怀疑是 fixture 的 setup/teardown 慢,可以同时跑 python -m pytest --setup-show 看执行顺序;--durations 的排序更适合锁定具体用例,别把它当成稳定基准。CI 里如果用了 xdist,也最好固定 worker 数,不然每次榜单可能会抖。
FinleyLv1#1 这个很适合先做第一轮定位。补一个小点:如果怀疑是 fixture 的 setup/teardown 慢,可以同时跑
python -m pytest --setup-show看执行顺序;--durations的排序更适合锁定具体用例,别把它当成稳定基准。CI 里如果用了 xdist,也最好固定 worker 数,不然每次榜单可能会抖。
还有个容易忽略的点:参数化测试的 nodeid 会把参数值带出来,慢的那一条通常能直接定位到具体输入。定位后可以单独重跑它:
python -m pytest 'tests/test_api.py::test_lookup[case-name]' -vv
在 Python 3.9+、pytest 7+ 项目里可用。nodeid 最好从前一次输出里原样复制,并把整段用引号包住,参数里有特殊字符时不容易被 shell 误处理。
Nathan03Lv1#2 还有个容易忽略的点:参数化测试的 nodeid 会把参数值带出来,慢的那一条通常能直接定位到具体输入。定位后可以单独重跑它:
python -m pytest 'tests/test_api.py::test_lookup[case-name]' -vv在 Python 3.9+、pytest 7+ 项目里可用。nodeid 最好从前一次输出里原样复制,并把整段用引号包住,参数里有特殊字符时不容易被 shell 误处理。
再补一个盲区:--durations 主要覆盖测试的 setup/call/teardown。要是整条命令很慢、榜单里的单测却都不长,可能耗在 collection、import 或插件钩子上。可以先跑:
python -m pytest --collect-only -q
它只收集不执行,用来判断是不是在真正跑测试前就卡住了。Python 3.9+、pytest 7+ 可用;参数化用例再结合上面的 nodeid 单独重跑,定位会快不少。
如果 --collect-only 本身就慢,下一步可以先排除插件和导入:对可疑插件临时加 -p no:插件名,看耗时有没有明显变化。
还可以试试:
python -X importtime -m pytest --collect-only -q
它会把导入耗时打出来,输出有点吵,但能看出是不是 conftest.py 或某个插件在收集前拖住了。这个阶段慢,通常和测试函数本身没关系。
别熬夜啦Lv1#4 如果
--collect-only本身就慢,下一步可以先排除插件和导入:对可疑插件临时加-p no:插件名,看耗时有没有明显变化。还可以试试:
python -X importtime -m pytest --collect-only -q它会把导入耗时打出来,输出有点吵,但能看出是不是
conftest.py或某个插件在收集前拖住了。这个阶段慢,通常和测试函数本身没关系。
还可以临时关掉第三方插件自动加载,判断是不是插件本身拖慢了收集:
PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python -m pytest --collect-only -q
这个环境变量只影响通过入口点自动发现的插件,项目里的 conftest.py 仍会参与。若速度明显恢复,再逐个恢复插件比盲目改测试更容易定位。Python 3.9+、pytest 7+ 可用。