在Django 1.7中运行unit testing时禁用迁移

Django 1.7引入了数据库迁移 。

在Django 1.7中运行unit testing时,它会强制迁移 ,这需要很长时间。 所以我想跳过Django的迁移,并创build最终状态的数据库。

我知道忽略迁移可能是一个不好的做法,因为这部分代码不会被testing。 但事实并非如此:我在CItesting服务器上运行完整的迁移(jenkins)。 我只想跳过速度很重要的本地testing中的迁移。


一些背景:

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

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

如果您希望testing运行程序使用syncdb而不是迁移 – 例如,如果您的迁移时间过长,则只需在settings.py中设置SOUTH_TESTS_MIGRATE = False即可。

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

从Django 1.8开始,我将使用–keepdb参数:

–keepdb选项可用于在testing运行之间保留testing数据库。 这具有跳过创build和销毁操作的优点,这大大减less了运行testing的时间,尤其是在大型testing套件中。 如果testing数据库不存在,则将在第一次运行时创build,然后保留以备后续运行。 在运行testing套件之前,任何未应用的迁移也将被应用到testing数据库。

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

看看这个解决方法 ,由Bernie Sumption发布到Django开发者邮件列表:

如果makemigrations尚未运行,那么“migrate”命令会将应用程序视为未迁移,并像1.6中的syncdb一样直接从模型创build表。 我为一个名为“settings_test.py”的unit testing定义了一个新的设置模块,它将从主设置模块中导入*并添加下面的代码:

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

然后我运行这样的testing:

DJANGO_SETTINGS_MODULE =“myapp.settings_test”python manage.pytesting

这个傻子想到应用程序没有被移植,所以每次创build一个testing数据库时,都会反映出models.py的当前结构。

在Django 1.9中,这种情况有所改善 ,您可以将值设置为None

MIGRATION_MODULES = {“myapp”:无}

这是我的设置文件的结尾:

 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() 

基于这个片段

我只在testing运行时禁用迁移

django-test-without-migrations为manage.py test添加了一个--nomigrations标志。 奇迹般有效。

更新 :没关系,这个变化在1.10 final被释放之前被恢复了 。 希望它会在未来的版本中返回。


请注意,从Django 1.10开始,这可以通过testing数据库设置进行控制。

迁移

默认值: True

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

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

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

对于Django 1.9而言,Guillaume Vincent的答案已经不再适用了,所以这里有一个新的解决scheme:

我在INSTALLED_APPS的定义之后,在我的设置文件中使用了这个片段

 if os.environ.get('TESTS_WITHOUT_MIGRATIONS', False): MIGRATION_MODULES = { app.split('.')[-1]: None for app in INSTALLED_APPS } 

它遍历所有安装的应用程序,并将其标记为没有迁移模块。 有关更多信息,请参阅django文档 。

使用这个片段,你可以运行你的testing,设置环境variablesTESTS_WITHOUT_MIGRATIONS ,例如:

 TESTS_WITHOUT_MIGRATIONS=1 ./manage.py test