我们使用django迁移(django v1.7 +)更改了我们的数据库。 数据库中存在的数据不再有效。
基本上我想在单元测试中测试迁移,构建迁移前数据库,添加一些数据,应用迁移,然后确认一切顺利。
如何:
在加载unittest时阻止新迁移
我发现some stuff有关覆盖settings.MIGRATION_MODULES
的问题,但无法确定如何使用它。当我检查executor.loader.applied_migrations
时,它仍会列出所有内容。我可以阻止新迁移的唯一方法是实际删除文件;不是我可以使用的解决方案。
在unittest数据库中创建记录(使用旧模型)
如果我们可以阻止迁移,那么这应该非常简单。 myModel.object.create(...)
应用迁移
我想我可以解决这个问题,因为我找到了test_executor:设置一个指向迁移文件的计划并执行它?嗯,对吗?有任何代码:-D
确认数据库中的旧数据现在与新模型匹配
同样,我希望这应该很简单:只需获取迁移前创建的实例,并确认它已经以正确的方式进行了更改。
因此,挑战实际上只是解决如何阻止unittest应用最新的迁移脚本,然后在我们准备好后应用它?
也许我的方法不对?我应该创建固定装置,并确认它们最终都是好的吗?在应用迁移之前,还是在完成迁移之后,是否会加载夹具?
使用MigrationExecutor
并使用.migrate
选择特定的迁移,我可以,也许?,将其回滚到特定状态,然后逐个前滚。但这引起了怀疑;由于缺少实际的ALTER TABLE指令,目前正在追逐sqlite捏造。陪审团还在外面。
答案 0 :(得分:3)
我无法使用当前数据库架构阻止启动的单元测试,但我确实发现很容易恢复到迁移历史记录中的早期点:
其中“0014_nulls_permitted”是迁移目录中的文件...
from django.db.migrations.executor import MigrationExecutor
executor.migrate([("workflow_engine", "0014_nulls_permitted")])
executor.loader.build_graph()
NB: 在executor.loader.build_graph
的调用之间运行executor.migrate
似乎是完成迁移并使事情按照人们的预期行事的一个非常重要的部分/ em>的
可以使用以下内容检查当前适用于数据库的迁移:
print [x[1] for x in sorted(executor.loader.applied_migrations)]
[u'0001_initial', u'0002_fix_foreignkeys', ... u'0014_nulls_permitted']
我通过ORM创建了一个模型实例,然后通过直接运行一些SQL来确保数据库处于旧状态:
job = Job.objects.create(....)
from django.db import connection
cursor = connection.cursor()
cursor.execute('UPDATE workflow_engine_job SET next_job_state=NULL')
大。现在我知道我有一个旧状态的数据库,可以测试前向迁移。所以0016_nulls_banished是一个迁移文件:
executor.migrate([("workflow_engine", "0016_nulls_banished")])
executor.loader.build_graph()
迁移0015通过数据库将所有NULL字段转换为默认值。迁移0016会更改架构。您可以分散一些打印报表,以确认事情正在发生,因为您认为应该如此。
现在测试可以确认迁移是否有效。在这种情况下,通过确保数据库中没有空值。
jobs = Job.objects.all()
self.assertTrue(all([j.next_job_state is not None for j in jobs]))
答案 1 :(得分:-1)
我们在settings_test.py
中使用了以下代码来忽略测试的迁移:
MIGRATION_MODULES = dict(
(app.split('.')[-1], '.'.join([app, 'nonexistent_django_migrations_module']))
for app in INSTALLED_APPS
)
这里的想法是没有任何应用程序有nonexistent_django_migrations_module
文件夹,因此django只会找不到迁移。