在创建测试数据库时禁用Django中的数据迁移

时间:2017-06-12 09:59:06

标签: django migration automated-tests

我有一个包含大量迁移的应用,包括在某些模型上设置外键的数据迁移。

当我尝试运行tests.py时,它会失败,因为数据迁移正在向数据库查询测试数据库中不存在的数据。

有没有办法禁用数据迁移? (我想保留架构迁移,而不是完全禁用迁移)。

或者在运行数据迁移之前从夹具加载数据?

5 个答案:

答案 0 :(得分:2)

首先,我应该注意到这个解决方案是一个肮脏的伎俩:)

我认为您应检查测试是否正在运行,如果答案为True,则将数据迁移排除在执行之外。 要检查测试是否正在运行,您可以定义自己的DiscoverRunner并设置一个变量,显示测试现在正在运行。

  

测试运行器是一个定义run_tests()方法的类。 Django附带了一个DiscoverRunner类,用于定义默认的Django测试行为。此类定义run_tests()入口点,以及run_tests()用于设置,执行和拆除测试套件的其他方法。

例如,在您的设置中定义TEST_RUNNER。

from django.conf import settings
from django.test.runner import DiscoverRunner

class MyTestSuiteRunner(DiscoverRunner):
    def __init__(self, *args, **kwargs):
        settings.TEST_RUN = True
        super().__init__(*args, **kwargs)

TEST_RUNNER = 'project_name.test_settings.MyTestSuiteRunner'

我们假设您的应用中只有两次迁移:

  • 0001_initial.py
  • 0002_data_migration.py

因此,您应该检查data_migration是否正在运行测试并且是否包含您的操作。

from your_app.settings import settings
class Migration(migrations.Migration):

    dependencies = [
        ('your_app', '0001_initial.py'),
    ]

    operations = [
        migrations.RunPython(data_migration_method),
    ] if not settings.TEST_RUN else []

我再次注意到,在我看来,这是一个肮脏的黑客,阅读它应该如何以正确的方式制作会很有趣,但这个解决方案可能有助于解决保存迁移依赖性的问题。 请注意,您也可以在test_settings中添加TEST_RUNNER运行测试,因为建议使用AR7。

同时检查TEST_RUNNER文档(https://docs.djangoproject.com/en/1.11/topics/testing/advanced/#defining-a-test-runner)。我希望它能帮助您找到更好的解决方案。

另一种解决方案是使用django-pytest而不是标准的unittest模块。 Pytest提供了一组用于测试Django应用程序和项目的有用工具。它还有助于禁用Django迁移并通过检查所有模型来创建数据库。只需使用--nomigrations标志运行测试。阅读文档以获取更多信息(https://pytest-django.readthedocs.io/en/latest/database.html#nomigrations-disable-django-1-7-migrations

答案 1 :(得分:1)

您可以从settings.py文件中禁用迁移以加快测试速度。请为测试创建单独的设置文件,并输入以下代码以禁用迁移:

MIGRATION_MODULES = {
'auth': None,
'contenttypes': None,
'default': None,
'sessions': None,

'core': None,
'profiles': None,
'snippets': None,
'scaffold_templates': None,
}

要使用自定义设置文件运行测试,请使用以下命令

python manage.py test --settings=project.tests_settings 

答案 2 :(得分:1)

要检查测试是否正在运行:

{{1}}

答案 3 :(得分:0)

您可以使用--keepdb

运行测试

django docs:

  

使用。可以防止测试数据库被破坏   test --keepdb选项。这将保留测试数据库   运行。如果数据库不存在,将首先创建它。任何   还将应用迁移以使其保持最新。

所以你创建一个包含有效数据的测试数据库,并应用最新的迁移,然后运行测试,django将不会尝试在runnng测试时创建表或运行迁移: - )

请注意,我建议您更新数据迁移功能,而不是使用keepdb,以便能够在空数据集上运行它们(例如,在迁移功能的头部检查表是否为空,如果它为空返回并显示警告信息)

答案 4 :(得分:0)

我受到Disable migrations while testing@A. Grinenko的启发。我没有自定义TestRunner,只是检查了django test是否调用了0002_data_migration.py
代码:

class Migration(migrations.Migration):
dependencies = [
    ('backend', '0001_initial'),
]

operations = [
    migrations.RunPython(setup_data, rollback_setup, atomic=True)
] if 'test' not in sys.argv[1:] else []