如何仅在内存中运行Django的testing数据库?

我的Djangounit testing需要很长时间才能运行,所以我正在寻找加快速度的方法。 我正在考虑安装SSD ,但我也知道它也有缺点。 当然,有些事情我可以用我的代码做,但我正在寻找一个结构性的修复。 即使运行单个testing也很慢,因为每次都需要重build/南迁数据库。 所以这是我的想法

因为我知道testing数据库总是很小,为什么我不能configuration系统始终将整个testing数据库保存在RAM中? 切勿触摸磁盘。 我如何在Django中configuration? 我宁愿继续使用MySQL,因为这是我在生产中使用的,但如果SQLite 3或其他东西使这容易,我会这样。

SQLite或MySQL有一个选项可以完全在内存中运行吗? 应该有可能configuration一个RAM磁盘,然后configurationtesting数据库来存储它的数据,但我不知道如何告诉Django / MySQL使用一个不同的数据目录为特定的数据库,特别是因为它不断被擦除并重新创build每个运行。 (我正在使用Mac FWIW。)

如果在运行testing时将数据库引擎设置为sqlite3,则Django将使用内存数据库 。

我在我的settings.py使用这样的代码将引擎settings.py为sqlite运行我的testing时:

 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'} 

(后端的完整path并不是Django 1.3必须的,但是使设置向前兼容。)

您也可以添加以下行,以防南迁移出现问题:

  SOUTH_TESTS_MIGRATE = False 

我通常为testing创build一个单独的设置文件,并在testing命令中使用它

 python manage.py test --settings=mysite.test_settings myapp 

它有两个好处:

  1. 您不必在sys.argv中检查test或任何这样的魔术词, test_settings.py可以简单地

     from settings import * # make tests faster SOUTH_TESTS_MIGRATE = False DATABASES['default'] = {'ENGINE': 'django.db.backends.sqlite3'} 

    或者,您可以根据自己的需要进一步调整,将testing设置与生产设置完全分开。

  2. 另一个好处是你可以用生产数据库引擎来运行testing,而不是使用sqlite3来避免细微的错误,所以在开发中使用

     python manage.py test --settings=mysite.test_settings myapp 

    并在提交代码之前运行一次

     python manage.py test myapp 

    只是为了确保所有的testing都真的过去了。

MySQL支持一个名为“MEMORY”的存储引擎,您可以在数据库configuration( settings.py )中configuration这个存储引擎,如下所示:

  '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这不适用于您。

我无法回答你的主要问题,但有几件事情你可以做,以加快速度。

首先,确保你的MySQL数据库被设置为使用InnoDB。 然后它可以使用事务在每次testing之前回滚db的状态,这在我的经验中已经导致了大量的加速。 您可以在settings.py(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" } } } 

其次,你不需要每次都运行南迁。 在settings.py中设置SOUTH_TESTS_MIGRATE = False ,数据库将使用普通的syncdb创build,这比在所有历史迁移中运行快得多。

你可以做双重调整:

  • 使用事务表:在每个TestCase之后,将使用数据库回滚来设置初始状态。
  • 把你的数据库数据目录放在ramdisk上:就数据库的创build而言,你会获得很多,运行testing也会更快。

我使用两种技巧,我很高兴。

如何在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 

小心,这只是为了testing,重新启动后,你的数据库从内存中丢失!

另一种方法:让另一个MySQL实例运行在使用RAM磁盘的临时文件中。 在这个博客文章中的说明: 加快MySQL在Django进行testing

优点:

  • 您使用生产服务器使用完全相同的数据库
  • 不需要改变你的默认mysqlconfiguration

扩展Anurag的答案,我通过创build相同的test_settings并将以下内容添加到manage.py来简化了过程

 if 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只能通过命令行使用,所以看起来更清洁,所以不需要混乱设置