Python CI 中测试为什么会变慢?

10次阅读

python CI 测试变慢主因是环境初始化、依赖安装、并行不足、I/O/网络未 Mock 及镜像不一致;应缓存 pip、分层安装依赖、合理使用 pytest-xdist、Mock 外部调用、固定基础镜像版本。

Python CI 中测试为什么会变慢?

Python CI 中测试变慢,通常不是单一原因导致的,而是多个环节叠加的结果。核心问题往往出在环境初始化、依赖安装、测试并行性、I/O 和网络行为上,而不是测试代码本身。

依赖安装耗时长

每次 CI 运行都从头拉取和安装全部依赖(尤其是 numpypandastorch 等含编译扩展的包),会显著拖慢整体流程。

  • 使用 缓存 pip 包目录(如 gitHub Actions 的 actions/cache 缓存 ~/.cache/pip
  • 避免在 requirements.txt 中混用 --pre 或频繁变动版本号,破坏缓存命中率
  • 考虑分层依赖:把稳定的基础包(如 pytestrequests)和易变的业务依赖分开安装

测试未合理并行或隔离

默认单进程执行 pytest 会浪费多核资源;而盲目开启高并发又可能因共享资源(如数据库、临时文件、端口)引发冲突和重试。

  • pytest-xdist 并指定合理进程数(如 -n 4),避免超过 CI 机器 vCPU 数
  • 确保测试间无状态、不共用全局变量或磁盘路径;用 tmp_path 或内存数据库(如 sqlite:///:memory:)替代真实 DB
  • 对耗时长的测试打标签(如 @pytest.mark.slow),CI 中可选择性跳过或单独调度

隐式 I/O 和网络调用未 Mock

看似单元测试,实则调用了本地文件读写、http 请求、redis 连接等——这些在 CI 环境中延迟更高、更不稳定,且无法复用缓存。

立即学习Python免费学习笔记(深入)”;

  • 检查是否遗漏 requests.getopen()subprocess.run 等调用,统一用 pytest-mockresponses 替换
  • 避免在 conftest.py 中做一次性耗时初始化(如下载测试数据),改用 pytest.fixture(scope="session") + 条件缓存
  • 使用 pytest-timeout 快速暴露卡死测试,而非让整个 job 超时失败

CI 镜像与本地环境不一致

本地快速跑过的测试,在 CI 里变慢,常因底层差异:glibc 版本、Openssl 行为、甚至 CPU 架构(如 apple Silicon vs x86_64 docker 镜像)。

  • 固定基础镜像版本(如 python:3.11-slim-bookworm),避免 python:3.11-slim 自动漂移
  • 在 CI 中添加 python -c "import sys; print(sys.version, sys.implementation.name)" 日志,确认解释器一致
  • 若用 PyPy 或 conda,注意其启动和 JIT 暖机时间比 CPython 更长,需单独评估
text=ZqhQzanResources