【发布时间】:2014-05-01 23:27:53
【问题描述】:
我们在 Ubuntu 12.04 上使用 Django 1.4 和 PostgreSQL。我们有很多测试,问题是运行测试非常慢,我认为因为对于每个测试,数据库都是从头开始创建的。我想通过在内存(而不是硬盘)中使用数据库运行测试来加快测试速度。我该怎么做?有链接或者教程吗?
【问题讨论】:
标签: django postgresql django-testing in-memory-database django-tests
我们在 Ubuntu 12.04 上使用 Django 1.4 和 PostgreSQL。我们有很多测试,问题是运行测试非常慢,我认为因为对于每个测试,数据库都是从头开始创建的。我想通过在内存(而不是硬盘)中使用数据库运行测试来加快测试速度。我该怎么做?有链接或者教程吗?
【问题讨论】:
标签: django postgresql django-testing in-memory-database django-tests
在 Django 1.9 中,如果你有一个多核处理器,一个很好的选择就是 flag:
--parallel
这需要您pip install tblib,但可以让您在多个内核上同时运行单元测试。 (https://docs.djangoproject.com/en/1.10/ref/django-admin/#cmdoption-test-parallel)
Django 1.8+ 的另一个不错的选择是标志:
--keepdb
它会重用您的测试数据库,从而避免您每次运行测试时创建新的测试数据库所导致的漫长等待时间。 (https://docs.djangoproject.com/en/1.10/ref/django-admin/#cmdoption-test-keepdb
【讨论】:
--keep-db 使测试更快,但它只能在本地使用,实际测试(例如您在 CICD 中运行的测试)不应该使用它。它可能会阻止您发现一些问题,尤其是与模型和迁移相关的问题。
最好的选择是为您的测试提供一个单独的设置文件。在 settings_test.py 你告诉它使用默认使用内存数据库的 sqlite:
from base_settings import *
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory'
}
}
然后通过添加 --settings=settings_test 来运行您的测试
另请参阅 Django 文档:
https://docs.djangoproject.com/en/dev/topics/testing/overview/#the-test-database
【讨论】:
--keepdb 运行通常与内存中的瞬态 SQLite 一样快或更快。
有几个有用的 SO 线程:
我确实使用 SQLite 技巧来进行完整性检查,但如果您正在做任何特定于数据库的事情,它会让您发疯:某些 SQL 差异,差异是数据精度等。它也削弱了测试的意义:如果您使用测试来向您保证更改一旦推送到生产环境就会起作用,那么针对不同的数据库运行它们并不是一个好方法。尽可能尝试使用鼻子跳过数据库重新创建并优化您的本地 Postgres 设置。你可以试试avoiding the DB altogether as well.
最适合我的事情是尝试将测试造成的停机时间视为提出更好更改的机会,并鼓励我在启动测试运行程序之前思考我正在更改的内容。
【讨论】:
快进到 2016 年,我们在 manage.py 中有一个很好的 option 来加快测试速度。
--keepdb, -k¶ Django 1.8 中的新功能。在测试运行之间保留测试数据库。这具有跳过创建和 破坏可以大大减少运行测试时间的操作, 尤其是大型测试套件中的那些。如果测试数据库没有 存在,它将在第一次运行时创建,然后为每个 后续运行。任何未应用的迁移也将应用于 在运行测试套件之前测试数据库。
如果您不使用 TransactionTestCase 及其子类,则大部分测试运行时间将来自数据库创建。如果您有大量迁移,那将非常糟糕。但是你用
来避免这一切 ./manage.py test -k myapp
【讨论】:
您可以简单地将用于测试的数据库更改为 sqlite:
import sys
if 'test' in sys.argv:
DATABASES['default']['engine'] = 'sqlite3'
请注意,由于数据库之间的某些不兼容,您的某些测试可能会失败,但通常这应该有效。
【讨论】:
不熟悉 python 或 Django,但从概念上讲,您应该能够:
(如果 ORM 不支持保存点,您可能需要在测试期间覆盖 ORM 的开始/结束事务代码。)
http://www.postgresql.org/docs/current/static/sql-savepoint.html
(我要补充一点,在概念层面上,您的 DBAL 和 ORM 应该在您的测试中被模拟,以便您单独测试您的组件。也就是说,您可能不应该连接到在您的大多数测试中都从数据库开始。)
【讨论】:
begin、rollback 和 commit 语句,它需要做发出savepoint tx、rollback to tx 和release tx。这样,它就永远不会真正承诺。不过,多连接测试很好。