我的Django单元测试需要很长时间才能运行,因此我正在寻找提高速度的方法。我正在考虑安装SSD,但我知道它也有缺点。当然,我可以用我的代码做些事情,但我正在寻找结构修复。即使运行单个测试也很慢,因为每次都需要重建/迁移数据库。所以这是我的想法......
因为我知道测试数据库总是很小,为什么我不能只是将系统配置为始终将整个测试数据库保存在RAM中?切勿触摸磁盘。如何在Django中配置它?我更喜欢继续使用MySQL,因为这是我在制作中使用的内容,但是如果SQLite 3或其他东西让我很容易,我就会这样做。
SQLite或MySQL是否可以选择完全在内存中运行?应该可以配置一个RAM磁盘然后配置测试数据库来存储它的数据,但是我不知道如何告诉Django / MySQL为某个数据库使用不同的数据目录,特别是因为它一直被擦除并重新创建每次运行。 (我在Mac FWIW上。)
答案 0 :(得分:155)
如果在运行测试时将数据库引擎设置为sqlite3,Django will use a in-memory database。
我在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 :(得分:80)
我通常会为测试创建一个单独的设置文件,并在测试命令中使用它,例如
python manage.py test --settings=mysite.test_settings myapp
它有两个好处:
您不必在sys.argv中检查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
只是为了确保所有测试都真的通过。
答案 2 :(得分:22)
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
,则无法使用此功能。
答案 3 :(得分:15)
我无法回答你的主要问题,但你可以采取一些措施来加快速度。
首先,确保您的MySQL数据库设置为使用InnoDB。然后它可以使用事务在每次测试之前回滚数据库的状态,这在我的经验中导致了大规模的加速。您可以在settings.py(Django 1.2语法)中传递数据库init命令:
DATABASES = {
'default': {
'ENGINE':'django.db.backends.mysql',
'HOST':'localhost',
'NAME':'mydb',
'USER':'whoever',
'PASSWORD':'whatever',
'OPTIONS':{"init_command": "SET storage_engine=INNODB" }
}
}
其次,您不需要每次都运行South迁移。在settings.py中设置SOUTH_TESTS_MIGRATE = False
,数据库将使用plain syncdb创建,这比运行所有历史迁移要快得多。
答案 4 :(得分:10)
你可以做双重调整:
我正在使用这两种技巧,我很开心。
如何在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 :(得分:3)
另一种方法:在使用RAM磁盘的tempfs中运行另一个MySQL实例。本博文中的说明: Speeding up MySQL for testing in Django。
优点:
答案 6 :(得分:2)
扩展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 :(得分:0)
在下面的setting.py
DATABASES['default']['ENGINE'] = 'django.db.backends.sqlite3'