You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

pytest执行1800个测试耗时超10分钟,builtins.compile占比高原因排查

排查方向与解决方法

1. pytest 配置不当导致的频繁compile

  • 检查测试扫描范围配置
    没有明确限制测试扫描路径时,pytest会递归遍历当前目录下所有可识别的Python文件,虚拟环境、临时脚本目录、静态资源目录下的py文件都会被编译,直接推高耗时。
    你可以在pytest.ini/pyproject.toml中添加配置限制扫描范围:
    [pytest]
    testpaths = tests  # 仅扫描tests目录下的测试文件
    norecursedirs = venv .git __pycache__ dist build  # 排除不需要扫描的目录
    
  • 检查字节码缓存是否被禁用
    如果环境变量设置了PYTHONDONTWRITEBYTECODE=1,或者运行pytest时添加了--no-cache-dir参数,会导致每次运行都要重新编译所有py文件,无法复用之前生成的.pyc字节码缓存。去掉上述配置后再运行测试,验证耗时是否下降。
  • 检查断言重写相关配置
    pytest默认的断言重写逻辑会调用builtins.compile处理测试文件的断言逻辑,如果你的测试文件里有大量动态生成的断言语句,或者配置了自定义断言处理插件,也可能触发额外的compile调用。你可以临时加--assert=plain参数运行测试,验证耗时是否有明显下降,如果下降明显再针对性排查断言相关插件的问题。

2. 业务代码/依赖库的compile调用

  • 定位调用源
    运行以下命令生成火焰图,直接定位builtins.compile的调用栈:
    py-spy record -o pytest_profile.svg -- pytest <你的测试运行参数>
    
    从火焰图中可以直接看到是pytest内部,还是第三方依赖、业务代码在调用compile。
  • 常见高耗时场景排查
    • 大量动态代码生成逻辑:比如用exec/eval动态生成测试用例、动态生成ORM模型、动态渲染模板(如Jinja2每次运行都重新编译模板字符串),都会触发大量compile调用。
    • 参数化测试使用不当:如果用循环+exec的方式动态生成测试函数,替代原生的@pytest.mark.parametrize,每次运行都会重复编译动态生成的代码,耗时会大幅提升。
    • 未缓存的正则编译:虽然你已经优化了部分正则编译调用,还要检查是否有运行时循环编译正则的逻辑,没有复用编译后的正则对象。

3. 快速定位问题阶段

运行pytest --collect-only仅执行测试收集逻辑,不运行实际测试用例:

  • 如果该步骤耗时已经接近9分钟,问题完全出在测试发现/编译阶段,优先排查第一类配置问题
  • 如果该步骤耗时很短,大部分耗时出现在测试执行阶段,优先排查第二类依赖/业务代码问题

内容的提问来源于stack exchange,提问作者Deepak Selvakumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 04:15:03