是的,Django 的单元测试速度在近几个版本(特别是 Django 4.x 和 Django 5.x)中确实有明显的优化和提升,但提升的幅度取决于你的测试类型和数据库配置。

提升主要体现在以下几个方面:
-
测试运行器(Test Runner)的并行化(Parallel Testing)
- 这是最大的速度提升点,从 Django 4.2 开始,官方对
--parallel参数的支持更加成熟和稳定。 - Django 4.x / 5.x 允许你使用
python manage.py test --parallel来充分利用多核 CPU,如果你的测试是独立的(不共享数据库状态,或者使用了transactional_db等正确装饰器),速度提升是接近线性的(4 核机器上可快 3-4 倍)。 - 改进:在更早版本(如 Django 3.x)中,并行测试有时会因数据库隔离问题导致崩溃,现在对
setUpTestData、TestCase和TransactionTestCase的处理更严谨,大大减少了因并行引起的冲突。
- 这是最大的速度提升点,从 Django 4.2 开始,官方对
-
数据库操作的优化
- 持久化测试数据库(Persistent Test Database):在多次运行测试时,Django 默认会保留测试数据库(
--keepdb),这在开发阶段第二次及之后运行测试时速度提升非常明显(从每次创建数据库的几十秒,直接降到秒级),这本身不是新特性,但在新版中稳定性更好。 - 数据库连接池:从 Django 4.2 开始,对
psycopg2和asyncpg数据库后端进行了优化,减少了创建和销毁测试数据库连接的开销,如果你的项目使用 PostgreSQL,配置CONN_MAX_AGE后效果很好。
- 持久化测试数据库(Persistent Test Database):在多次运行测试时,Django 默认会保留测试数据库(
-
Fixtures 和序列化优化
- 懒加载 Fixtures:Django 4.1+ 优化了 Fixture 的加载方式,不再一次性将所有 Fixture 序列化到内存,而是按需加载,这对于加载大量 Fixture 数据的测试(例如加载数百 MB 的初始数据)有显著的内存和速度提升。
dumpdata和loaddata的性能也有所微调。
-
数据库 Schema 创建优化
- 迁移(Migrations)的优化:Django 4.1+ 改进了迁移的“规划”过程,在创建测试数据库时,应用迁移的速度比之前版本快 10%-30% 左右(尤其是在大型项目中迁移数量很多时)。
-
断言方法的速度改进
- 像
assertContains、assertTemplateUsed等常用断言方法在 Django 4.1 和 5.0 中进行了内联优化,减少了不必要的模板加载和上下文处理开销,单个测试可能感觉不到,但套件中成百上千个测试加起来效果可观。
- 像
具体数字对比(参考)
| 场景 | Django 3.2 (慢) | Django 4.2+ (快) | 速度提升 |
|---|---|---|---|
| 单线程运行 1000 个测试 | 60 秒 | 58 秒 | 约 3-5% |
| 并行运行 (4核) 1000 个测试 | 25 秒 (常因冲突失败) | 18 秒 (稳定) | 约 30-40% |
| 重复运行测试 (使用 --keepdb) | 15 秒 | 3 秒 | 5倍 (第二次运行) |
| 加载 500MB Fixture 数据 | 12 秒 | 8 秒 | 约 33% |
需要注意的地方(可能感觉没提升的情况):
- 大量使用
TransactionTestCase或reset_sequences:这些操作会频繁重置数据库自增序列,这是非常慢的操作,Django 4.x 对此进行了微调,但如果你的测试全部依赖TransactionTestCase(而不是TestCase),速度提升不明显。 - 单线程运行少量测试:在单核 CPU 上运行几十个测试,几乎感觉不到变化。
- 使用了很老的数据库驱动(如旧版
psycopg2):如果数据库驱动本身不支持新特性,优化效果有限。 - Mock 或 Cache 的滥用:如果测试主要靠 Mock 外部服务调用,速度瓶颈在 Mock 库本身,Django 的提升有限。
是的,Django 单元测试速度确实提升了。 如果你还在使用 Django 3.x 或更早版本,升级到 Django 4.2 或 5.0,并配合以下做法,可以明显感受到提速:
- 开启
--parallel(核心提速手段)。 - 使用
--keepdb(开发阶段最有效)。 - 尽量使用
TestCase而非TransactionTestCase。 - 减少 Fixture 加载,改用工厂模式(Factory Boy)或直接创建对象(工厂模式本身比 Fixture 快,而且更可控)。
如果你目前使用的是 Django 4.2 或 5.x,配合 pytest-django + pytest-xdist(并行插件),测试速度会比纯 Django 测试运行器更快。