如何在 Django 中更快地测试迁移?



我尝试过在特定迁移文件上编写测试。基本上,我想测试一对迁移之间的数据库和数据的当前状态。我按如下方式使用了MigrationExecutor

executor = MigrationExecutor(connection)
old_apps = executor.loader.project_state(self.migrate_from).apps
executor.migrate(self.migrate_from)
# do something here
executor.migrate(self.migrate_to)

我们在项目中有很多迁移文件,因此使用单元测试运行所有这些文件需要花费大量时间。通常,我会在 asettings_test.py中将迁移模块设置为None

MIGRATION_MODULES: {
'my_app': None
}

使用此设置,测试将运行得非常快。问题是无法再找到要测试的迁移文件(self.migrate_fromself.migrate_to):

django.db.migrations.exceptions.NodeNotFoundError: Node ('poleluxe', '0090_auto_previous_migration') not a valid node

因此,我不得不在测试中再次包含迁移模块。

有没有办法在不运行所有迁移文件的情况下包含它们?就我而言,我想跳过从00010089的所有迁移,并仅运行0090(如self.migration_from)和0091(如self.migrate_to)。

我正在考虑压缩前 89 次迁移并将结果与00900091一起放在一个单独的文件夹中,然后在测试中引用该迁移文件夹。但是,我不确定这是否是一个很好的解决方案。

这是我目前所理解的,如果我不正确,请指导我。

问题所在

迁移
  1. 测试代码需要应用迁移。
  2. Django 比任何其他进程(如@override_settingsetUpClass())更早启动

解决方案

即使在 TestClass 未完全初始化的情况下,也要覆盖 TestClass 开头MIGRATION_MODULES设置,因为这是我只找到正确点的地方。

这样,您不仅可以禁用所有迁移以在运行测试时加快速度,还可以测试迁移文件。

  1. 禁用从settings.py的所有迁移。

    MIGRATION_MODULES = {app: None for app in INSTALLED_APPS}
    
  2. (可选)如果你使用 pytest-django,请从 pytest 设置中删除--nomigrations选项。
  3. 覆盖"MIGRATION_MODULES"设置,并在测试后将其重新设置。

    class TestMigrations(TestCase):
    origin_modules = getattr(settings, 'MIGRATION_MODULES', {})
    setattr(settings, 'MIGRATION_MODULES', {})    
    ...
    @classmethod
    def tearDownClass(cls):
    setattr(settings, 'MIGRATION_MODULES', cls.origin_modules)
    super().tearDownClass()
    

试用信息

  1. @override_setting在测试类或测试方法上不起作用,因为 Django 在@override_setting装饰之前启动和运行迁移
  2. pytest-django 与--nomigrations不太确定,但我的解决方法是禁用从 Django 设置而不是 pytest-django 的迁移

最新更新