pytest 如何找出跑得慢的测试

pytest --durations=N 列出最慢的 N 个测试阶段,--durations=0 配合 --durations-min=0 显示全部阶段耗时。配合 --durations-min 设阈值、pytest-xdist 并行提速,本文给出完整的慢测试排查方案。

最佳实践
测试检测与质量验证插画

一句话回答:用内置参数 pytest --durations=N——--durations=0 不限制条目数,但仍受最小显示阈值影响;--durations=10 只看最慢的 10 个阶段,--durations=1 只看最慢的一个阶段。输出按耗时分段(setup/call/teardown),直接定位优化目标。零插件,pytest 自带。

基本用法

pytest --durations=0 --durations-min=0  # 显示全部阶段
pytest --durations=10      # 最慢的 10 个
pytest --durations=1       # 最慢的那个

以下输出仅为说明格式的示例,并非本文运行结果:

============= slowest 10 durations =============
3.42s call     tests/test_api.py::test_full_sync
1.15s setup    tests/test_db.py::test_migration
0.87s call     tests/test_parser.py::test_large_file
...

call 是测试本体耗时,setup/teardown 是夹具耗时——夹具慢(比如每次都建数据库)也是常见元凶。

过滤噪音:只看超过阈值的

pytest --durations=0 --durations-min=0.5    # 只显示超过 0.5 秒的

测试多的项目建议组合使用,不然 0 输出太长。

找到之后怎么提速

  1. 慢在 fixture:把重夹具的作用域改大——@pytest.fixture(scope="module") 或 scope="session",共享资源;先确认跨测试共享不会污染状态,不能牺牲测试隔离
  2. 慢在 I/O/网络:mock 掉外部调用(pytest-mock、responses),单元测试不该碰真网络
  3. 慢在数量:pip install pytest-xdist 后 pytest -n auto 多进程并行,收益取决于测试粒度、调度开销、I/O 和资源竞争,不与核数线性对应
  4. 慢在个别大测试:拆参数化、标记 @pytest.mark.slow 后在快速套件里跳过(-m "not slow")

CI 里盯趋势

把 pytest --durations=20 加进 CI 日志,慢测试的变化趋势可见;严格的团队会设总时长预算,超时即失败,防止测试套件悄悄变慢。

常见问题(FAQ)

Q:--durations=0 和 --durations 很大数(如 9999)有区别吗?

A:不总等价:0 表示不限条目数,9999 仍有上限;两者都受 --durations-min 约束。输出里仍会按 setup/call/teardown 分段列出。

Q:能导出耗时数据做进一步分析吗?

A:可以。pytest --junitxml=report.xml 生成的 JUnit XML 里每个用例带 time 属性,CI 系统(Jenkins/GitLab)能直接解析展示趋势图;也可以用 pytest-reportlog 等插件拿结构化数据。

Q:为什么同一测试每次耗时差异很大?

A:首次运行的编译缓存、磁盘缓存、外部服务波动都会干扰。在相同环境重复测量并比较分布;--durations-min 只隐藏低于阈值的阶段,不能消除测量噪音,亚秒级热点也可能值得优化。

核查依据

本文依据官方文档核对,示例未在实际业务环境运行;上线前请按部署版本、权限与数据范围验证。


延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台