如何在内存中运行Django的测试数据库?
我的Django单元测试运行得很慢,所以我在想办法加快这个速度。我考虑安装一个固态硬盘(SSD),但我知道这也有一些缺点。当然,我可以在代码上做些优化,但我更想找一个结构上的解决办法。即使只运行一个测试也很慢,因为每次都需要重建数据库或者进行south迁移。所以我有了一个想法……
既然我知道测试数据库通常很小,为什么不把系统配置成总是把整个测试数据库放在内存里呢?完全不接触硬盘。那我该怎么在Django里配置呢?我更想继续使用MySQL,因为这是我在生产环境中使用的,但如果SQLite 3或者其他什么东西能让这个过程简单一些,我也愿意尝试。
SQLite或MySQL有没有选项可以完全在内存中运行?应该可以配置一个RAM磁盘,然后把测试数据库的数据存储在那里,但我不太确定怎么告诉Django/MySQL使用一个不同的数据目录,尤其是因为每次运行时它都会被删除和重新创建。(顺便说一下,我是在Mac上操作。)
8 个回答
MySQL有一种叫做“MEMORY”的存储引擎,你可以在你的数据库配置文件(settings.py
)中进行设置,方法如下:
'USER': 'root', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'OPTIONS': {
"init_command": "SET storage_engine=MEMORY",
}
需要注意的是,MEMORY存储引擎不支持blob或text类型的列,所以如果你使用了django.db.models.TextField
,那就不适用了。
我通常会为测试创建一个单独的设置文件,并在测试命令中使用它,比如:
python manage.py test --settings=mysite.test_settings myapp
这样做有两个好处:
你不需要在系统参数中检查
test
或其他类似的关键词,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
以确保所有测试都真的通过。
如果你在运行测试时把数据库引擎设置为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迁移时遇到问题,你还可以添加以下这一行:
SOUTH_TESTS_MIGRATE = False