我尝试过在特定迁移文件上编写测试。基本上,我想测试一对迁移之间的数据库和数据的当前状态。我按如下方式使用了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_from
和self.migrate_to
):
django.db.migrations.exceptions.NodeNotFoundError: Node ('poleluxe', '0090_auto_previous_migration') not a valid node
因此,我不得不在测试中再次包含迁移模块。
有没有办法在不运行所有迁移文件的情况下包含它们?就我而言,我想跳过从0001
到0089
的所有迁移,并仅运行0090
(如self.migration_from
)和0091
(如self.migrate_to
)。
我正在考虑压缩前 89 次迁移并将结果与0090
和0091
一起放在一个单独的文件夹中,然后在测试中引用该迁移文件夹。但是,我不确定这是否是一个很好的解决方案。
这是我目前所理解的,如果我不正确,请指导我。
问题所在
迁移- 测试代码需要应用迁移。
- Django 比任何其他进程(如
@override_setting
和setUpClass()
)更早启动
解决方案
即使在 TestClass 未完全初始化的情况下,也要覆盖 TestClass 开头MIGRATION_MODULES
设置,因为这是我只找到正确点的地方。
这样,您不仅可以禁用所有迁移以在运行测试时加快速度,还可以测试迁移文件。
禁用从
settings.py
的所有迁移。MIGRATION_MODULES = {app: None for app in INSTALLED_APPS}
- (可选)如果你使用 pytest-django,请从 pytest 设置中删除
--nomigrations
选项。 覆盖"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()
试用信息
@override_setting
在测试类或测试方法上不起作用,因为 Django 在@override_setting
装饰之前启动和运行迁移- pytest-django 与
--nomigrations
不太确定,但我的解决方法是禁用从 Django 设置而不是 pytest-django 的迁移