问题:如何仅在内存中运行Django的测试数据库?
我的Django单元测试需要很长时间才能运行,因此我正在寻找加快速度的方法。我正在考虑安装SSD,但我知道它也有缺点。当然,我的代码可以做一些事情,但是我正在寻找结构上的修复方法。由于每次都需要重建/向南迁移数据库,因此即使运行单个测试也很慢。所以这是我的主意…
由于我知道测试数据库总是很小,所以为什么不能仅将系统配置为始终将整个测试数据库保留在RAM中?绝对不要触摸磁盘。如何在Django中配置它?我宁愿继续使用MySQL,因为这是我在生产中使用的方式,但是如果使用SQLite 3或其他方法可以简化这一点,我会采用这种方式。
SQLite或MySQL是否可以选择完全在内存中运行?应该可以配置RAM磁盘,然后配置测试数据库以将其数据存储在其中,但是我不确定如何告诉Django / MySQL为特定数据库使用不同的数据目录,特别是因为它不断被删除并重新创建每次运行。(我在Mac FWIW上。)
回答 0
如果在运行测试时将数据库引擎设置为sqlite3,则Django将使用内存数据库。
我settings.py
在运行测试时使用如下代码将引擎设置为sqlite:
if 'test' in sys.argv:
DATABASE_ENGINE = 'sqlite3'
或在Django 1.2中:
if 'test' in sys.argv:
DATABASES['default'] = {'ENGINE': 'sqlite3'}
最后在Django 1.3和1.4中:
if 'test' in sys.argv:
DATABASES['default'] = {'ENGINE': 'django.db.backends.sqlite3'}
(到Django 1.3并不一定要有完整的后端路径,但是可以使设置向前兼容。)
您还可以添加以下行,以防南向迁移出现问题:
SOUTH_TESTS_MIGRATE = False
回答 1
我通常为测试创建一个单独的设置文件,并在测试命令中使用它,例如
python manage.py test --settings=mysite.test_settings myapp
它有两个好处:
您不必检查
test
sys.argv中的任何此类神奇词,test_settings.py
只需from settings import * # make tests faster SOUTH_TESTS_MIGRATE = False DATABASES['default'] = {'ENGINE': 'django.db.backends.sqlite3'}
或者,您可以根据需要进一步调整它,将测试设置与生产设置完全分开。
另一个好处是您可以使用生产数据库引擎而不是sqlite3进行测试,从而避免了细微的错误,因此在开发使用时
python manage.py test --settings=mysite.test_settings myapp
并在提交代码之前运行一次
python manage.py test myapp
只是为了确保所有测试都通过了。
回答 2
MySQL支持称为“ MEMORY”的存储引擎,您可以在数据库config(settings.py
)中对其进行配置,如下所示:
'USER': 'root', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'OPTIONS': {
"init_command": "SET storage_engine=MEMORY",
}
请注意,MEMORY存储引擎不支持blob /文本列,因此,如果您使用django.db.models.TextField
此功能,则将无法使用。
回答 3
我无法回答您的主要问题,但是您可以做一些事情来加快速度。
首先,请确保您的MySQL数据库已设置为使用InnoDB。然后,它可以使用事务在每次测试之前回滚db的状态,以我的经验,这导致了极大的提速。您可以在settings.py中传递数据库init命令(Django 1.2语法):
DATABASES = {
'default': {
'ENGINE':'django.db.backends.mysql',
'HOST':'localhost',
'NAME':'mydb',
'USER':'whoever',
'PASSWORD':'whatever',
'OPTIONS':{"init_command": "SET storage_engine=INNODB" }
}
}
其次,您不需要每次都运行South迁移。设置SOUTH_TESTS_MIGRATE = False
在你的settings.py和数据库将与普通的执行syncdb,这将是比通过所有历史悠久的迁移运行更快创建。
回答 4
您可以进行两次调整:
- 使用事务表:在每个TestCase之后,将使用数据库回滚来设置初始固定装置状态。
- 将您的数据库数据目录放在ramdisk上:就数据库创建而言,您将获得很多收益,并且运行测试会更快。
我正在使用这两种技巧,我很高兴。
如何在Ubuntu上为MySQL设置它:
$ sudo service mysql stop
$ sudo cp -pRL /var/lib/mysql /dev/shm/mysql
$ vim /etc/mysql/my.cnf
# datadir = /dev/shm/mysql
$ sudo service mysql start
当心,这只是为了测试,从内存中重新启动数据库后,丢失了!
回答 5
另一种方法:让另一个MySQL实例在使用RAM磁盘的tempf中运行。这篇博客文章中的说明:加速MySQL以在Django中进行测试。
优点:
- 您使用与生产服务器完全相同的数据库
- 无需更改默认的mysql配置
回答 6
通过扩展Anurag的答案,我通过创建相同的test_settings并将以下内容添加到manage.py来简化了过程
if len(sys.argv) > 1 and sys.argv[1] == "test":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.test_settings")
else:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
似乎更干净,因为sys已经导入并且manage.py仅通过命令行使用,因此无需弄乱设置
回答 7
在您的下方使用 setting.py
DATABASES['default']['ENGINE'] = 'django.db.backends.sqlite3'