在Django 1.7中运行单元测试时禁用迁移

时间:2014-08-06 13:14:56

标签: django unit-testing django-migrations

Django 1.7 介绍了database migrations

在Django 1.7中运行单元测试时,会强制执行 migrate ,这需要很长时间。所以我想跳过django迁移,并在最终状态下创建数据库。

我知道忽略迁移可能是一种不好的做法,因为代码的那部分将不会被测试。但情况并非如此:我在CI测试服务器(jenkins)中运行完整迁移。我只想跳过本地测试中的迁移,速度很重要。


某些背景信息:

直到Django 1.6 ,使用South时,我使用了SOUTH_TESTS_MIGRATE设置:

  

默认情况下,如果South的syncdb命令以非交互模式运行(包括运行测试时),它也将应用迁移 - 每次运行测试时它都会运行每次迁移。

     

如果您希望测试运行器使用syncdb而不是迁移 - 例如,如果您的迁移需要太长时间才能应用 - 只需在settings.py中设置SOUTH_TESTS_MIGRATE = False。

但是, syncdb 不再存在,现在它迁移

从Django 1.8 我将使用 --keepdb 参数:

  

--keepdb选项可用于在测试运行之间保留测试数据库。这样做的优点是可以跳过create和destroy操作,这大大减少了运行测试的时间,特别是在大型测试套件中。如果测试数据库不存在,它将在第一次运行时创建,然后为每次后续运行保留。在运行测试套件之前,任何未应用的迁移也将应用于测试数据库。

所以这个问题仅限于Django 1.7。

7 个答案:

答案 0 :(得分:76)

看看this workaround,由Bernie Sumption发布到Django开发者邮件列表:

  

如果尚未运行makemigrations,则“migrate”命令会处理   一个应用程序作为未迁移,并直接从模型创建表   就像syncdb在1.6中所做的那样。我为单位定义了一个新的设置模块   称为“settings_test.py”的测试,它从main导入*   设置模块并添加以下行:

     

MIGRATION_MODULES = {“myapp”:“myapp.migrations_not_used_in_tests”}

     

然后我运行这样的测试:

     

DJANGO_SETTINGS_MODULE =“myapp.settings_test”python manage.py test

     

这个傻瓜移植到认为应用程序未迁移,等等   每次创建测试数据库时,它都会反映当前的数据   models.py的结构。

在Django 1.9中,这种情况为is improved somewhat,您可以将值设置为None

MIGRATION_MODULES = {“myapp”:无}

答案 1 :(得分:68)

以下是我的设置文件的结尾:

class DisableMigrations(object):

    def __contains__(self, item):
        return True

    def __getitem__(self, item):
        return None


TESTS_IN_PROGRESS = False
if 'test' in sys.argv[1:] or 'jenkins' in sys.argv[1:]:
    logging.disable(logging.CRITICAL)
    PASSWORD_HASHERS = (
        'django.contrib.auth.hashers.MD5PasswordHasher',
    )
    DEBUG = False
    TEMPLATE_DEBUG = False
    TESTS_IN_PROGRESS = True
    MIGRATION_MODULES = DisableMigrations()

基于此snippet

我仅在测试运行时禁用了迁移

答案 2 :(得分:28)

django-test-without-migrations--nomigrations添加manage.py test标记。像魅力一样。

答案 3 :(得分:3)

更新:没关系,在1.10 final发布之前,此更改为reverted。希望它将在未来版本中返回。

请注意,从Django 1.10开始,这可以通过测试数据库设置来控制。

  

迁移

     

默认值:True

     

如果设置为False,Django将不会使用迁移来创建测试数据库。

答案 4 :(得分:2)

https://gist.github.com/apollovy/22826f493ad2d06d9a9a22464730ce0b

MIGRATION_MODULES = {
    app[app.rfind('.') + 1:]: 'my_app.migrations_not_used_in_tests'
    for app in INSTALLED_APPS
}

答案 5 :(得分:1)

对于django 1.9以及Guillaume Vincent的答案不再适用,所以这是一个新的解决方案:

在定义INSTALLED_APPS

后,我在我的设置文件中使用此代码段
if os.environ.get('TESTS_WITHOUT_MIGRATIONS', False):
    MIGRATION_MODULES = {
        app.split('.')[-1]: None for app in INSTALLED_APPS
    }

它遍历所有已安装的应用,并将每个应用标记为没有迁移模块。请参阅django docs for more information

使用此代码段,您可以运行测试,设置环境变量TESTS_WITHOUT_MIGRATIONS,例如:

TESTS_WITHOUT_MIGRATIONS=1 ./manage.py test

答案 6 :(得分:-1)

我只是弄清楚如何在django 1.10之后禁用迁移,可能对某人有帮助。这是git的link

NewMember

django 1.10的迁移有两部分,请查看load_diskrecorder

class DisableMigrations(dict): def __contains__(self, item): return True def __getitem__(self, item): return None DATABASES = DisableMigrations() MIGRATION_MODULES = DisableMigrations() 添加的应用的迁移模型的load_disk部分 以及用于数据库连接的INSTALL_APP部分 对于1.9之前的版本,我们需要在运行测试时设置recorder 现在我们需要像MIGRATION_MODULES={'do.not.migrate':'notmigrations'}一样设置它 因此,如果我们不想为任何应用程序进行迁移,只需扩展一个dict并返回MIGRATION_MODULES={'do.not.migrate':None} None函数,并在getitem处执行相同操作,这是您需要的正确选项做

PS:对于命令,您需要在DATABASES之后指定--setting=module.path.settings_test_snippet PPS 如果您正在使用test 设置pycharm --settings选项,只需添加Run/Debug configurations的路径在自定义设置。那就好了!!

享受