如何在内存中运行Django的测试数据库?

135 投票
8 回答
56676 浏览
提问于 2025-04-16 00:18

我的Django单元测试运行得很慢,所以我在想办法加快这个速度。我考虑安装一个固态硬盘(SSD),但我知道这也有一些缺点。当然,我可以在代码上做些优化,但我更想找一个结构上的解决办法。即使只运行一个测试也很慢,因为每次都需要重建数据库或者进行south迁移。所以我有了一个想法……

既然我知道测试数据库通常很小,为什么不把系统配置成总是把整个测试数据库放在内存里呢?完全不接触硬盘。那我该怎么在Django里配置呢?我更想继续使用MySQL,因为这是我在生产环境中使用的,但如果SQLite 3或者其他什么东西能让这个过程简单一些,我也愿意尝试。

SQLite或MySQL有没有选项可以完全在内存中运行?应该可以配置一个RAM磁盘,然后把测试数据库的数据存储在那里,但我不太确定怎么告诉Django/MySQL使用一个不同的数据目录,尤其是因为每次运行时它都会被删除和重新创建。(顺便说一下,我是在Mac上操作。)

8 个回答

21

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,那就不适用了。

86

我通常会为测试创建一个单独的设置文件,并在测试命令中使用它,比如:

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

这样做有两个好处:

  1. 你不需要在系统参数中检查 test 或其他类似的关键词,test_settings.py 可以简单地是

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

    或者你可以根据自己的需要进一步调整它,把测试设置和生产设置清晰地分开。

  2. 另一个好处是,你可以用生产数据库引擎来运行测试,而不是使用sqlite3,这样可以避免一些细微的错误。因此,在开发时使用

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

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

    python manage.py test myapp
    

    以确保所有测试都真的通过。

177

如果你在运行测试时把数据库引擎设置为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

撰写回答