优先启用 pytest-xdist 并行执行,再配合 fixture 作用域精简和外部依赖 mock,就能解决绝大多数场景下的性能瓶颈;因其不改测试逻辑而仅优化调度,且能避免串行浪费多核资源、fixture 共享状态拖慢、i/o 不可控等问题。

Pytest测试套件变慢,90%的情况不是代码本身慢,而是执行方式或资源管理出了问题。直接上结论:优先启用 pytest-xdist 并行执行,再配合 fixture 作用域精简和外部依赖 mock,就能解决绝大多数场景下的性能瓶颈。
为什么 pytest-xdist 是第一优先级优化项
串行执行天然浪费多核 CPU 资源,尤其当测试用例数超过 200 个时,时间增长几乎线性。而 pytest-xdist 的核心价值在于它不改测试逻辑,只改执行调度——把独立测试分发到多个 worker 进程并行跑。
- 安装只需一条命令:
pip install pytest-xdist - 最稳妥的启动方式是:
pytest -n auto(自动匹配逻辑 CPU 数);若明确知道是 I/O 密集型(如大量 HTTP 请求、DB 查询),可手动设为物理核数 × 1.5,比如 8 核机器用-n 12 - 注意:如果测试间有共享状态(比如共用一个全局 DB 连接或写同一文件),并行会引发随机失败——这不是插件问题,而是测试设计缺陷,得先重构 fixture 隔离性
fixture 作用域滥用是隐形拖慢元凶
一个 @pytest.fixture(scope="session") 初始化数据库连接,却被 500 个测试函数调用,看似复用,实则让所有测试排队等这个单点资源。更糟的是,它还一直占着内存不释放。
- 原则:按实际使用频次选 scope —— 只被单个测试用,就用
scope="function";跨测试但不跨模块,用scope="class"或scope="module" - 高频初始化操作(如创建临时目录、启动轻量服务)务必加
yield+ 清理逻辑,否则残留资源会拖慢后续测试 - 避免在 fixture 中做耗时操作(如下载文件、生成大样本数据),改用参数化或预生成缓存
外部 I/O 是真实瓶颈,不是“看起来慢”
一个 requests.get("https://api.example.com") 在本地可能 200ms,在 CI 环境可能飙到 2s,且不可控。这类调用叠加后,测试总时长就失控了。
- 用
unittest.mock.patch替换真实请求是最直接解法,注意 patch 位置要精准(通常 patch 被测函数里 import 的位置,而非 requests 模块本身) - 数据库测试优先用内存 SQLite,而不是重装 PostgreSQL 容器;Testcontainers 场景下,开启容器复用(
reuse=True)能省掉 70% 启动时间 - 避免在
setup_method或 fixture 中重复读取大文件,改用模块级 fixture 一次性加载后共享
真正卡住的往往不是“怎么并行”,而是并行后暴露的隐式依赖——比如两个测试都往同一个临时表 insert 数据却没清理。这类问题不会报错,只会偶尔失败,调试成本远高于前期设计隔离。所以别急着调 -n 参数,先确保每个测试都能单独、稳定、快速地跑通。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











