如何对 Django 数据库迁移进行单元测试?

Joh*_*Mee 6 django django-models django-unittest

我们使用 django 迁移 (django v1.7+) 更改了我们的数据库。数据库中存在的数据不再有效。

基本上我想通过在单元测试中测试迁移,构建迁移前数据库,添加一些数据,应用迁移,然后确认一切顺利。

怎么做:

  1. 加载单元测试时阻止新的迁移

    我找到了一些关于覆盖的东西settings.MIGRATION_MODULES但不知道如何使用它。当我检查时,executor.loader.applied_migrations它仍然列出了所有内容。我可以阻止新迁移的唯一方法是实际删除文件;不是我可以使用的解决方案。

  2. 在 unittest 数据库中创建一条记录(使用旧模型)

    如果我们可以阻止迁移,那么这应该非常简单。 myModel.object.create(...)

  3. 应用迁移

    我想我现在可能可以解决这个问题,因为我已经找到了test_executor:设置一个指向迁移文件的计划并执行它?嗯,对吗?有任何代码:-D

  4. 确认数据库中的旧数据现在与新模型匹配

    同样,我希望这应该很简单:只需获取迁移前创建的实例并确认它已以所有正确的方式更改。

所以挑战真的只是解决如何防止单元测试应用最新的迁移脚本,然后在我们准备好时应用它?


也许我有错误的方法?我是否应该创建装置,并在最后确认它们都很好?是在应用迁移之前还是在它们全部完成之后加载夹具?


通过使用MigrationExecutor和挑选特定的迁移,.migrate我已经能够,也许?,将它回滚到特定状态,然后一个一个地向前滚动。但这令人怀疑;由于缺乏实际的 ALTER TABLE 指令,目前正在追逐 sqlite 捏造。陪审团还在外面。

Joh*_*Mee 5

我无法阻止单元测试的开始与当前数据库架构,但我没有找到它是很容易恢复到在迁移历史较早点:

其中“0014_nulls_permitted”是迁移目录中的文件...

from django.db.migrations.executor import MigrationExecutor
executor.migrate([("workflow_engine", "0014_nulls_permitted")])
executor.loader.build_graph()
Run Code Online (Sandbox Code Playgroud)

注意: 在 的调用之间运行似乎是完成迁移并使事情按预期运行的一个非常重要的部分executor.loader.build_graphexecutor.migrate

当前适用于数据库的迁移可以通过以下方式进行检查:

print [x[1] for x in sorted(executor.loader.applied_migrations)]

[u'0001_initial', u'0002_fix_foreignkeys', ... u'0014_nulls_permitted']
Run Code Online (Sandbox Code Playgroud)

我通过 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')
Run Code Online (Sandbox Code Playgroud)

伟大的。现在我知道我有一个处于旧状态的数据库,并且可以测试正向迁移。所以 0016_nulls_banished 是一个迁移文件:

executor.migrate([("workflow_engine", "0016_nulls_banished")])
executor.loader.build_graph()
Run Code Online (Sandbox Code Playgroud)

迁移 0015 通过数据库将所有 NULL 字段转换为默认值。迁移 0016 更改了架构。您可以散布一些打印语句,以确认事情正在按照您的想法发生。

现在测试可以确认迁移已经成功。在这种情况下,通过确保数据库中没有空值。

jobs = Job.objects.all()
self.assertTrue(all([j.next_job_state is not None for j in jobs]))
Run Code Online (Sandbox Code Playgroud)