【问题标题】:Disable data migrations in Django when creating test database创建测试数据库时在 Django 中禁用数据迁移
【发布时间】:2017-06-12 09:59:06
【问题描述】:

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

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

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

或者在运行数据迁移之前从固定装置加载数据?

【问题讨论】:

  • @e4c5 这与测试速度或禁用迁移完全无关。在试图说它是重复的之前,人们真的会费心阅读这个问题吗?

标签: django migration automated-tests


【解决方案1】:

您可以使用--keepdb 运行测试,

django 文档:

您可以通过使用 测试 --keepdb 选项。这将保留测试数据库之间 运行。如果数据库不存在,将首先创建它。任何 也将应用迁移以使其保持最新状态。

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


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

【讨论】:

  • 如果我有一个填充的测试数据库,那将很有用,但我没有。
  • 所以我认为您唯一的解决方案是更新您的迁移文件并按照我在回答的第二部分中所说的那样更新它们。
【解决方案2】:

检查是否正在运行测试:

'test' in sys.argv

【讨论】:

    【解决方案3】:

    我受到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 []
    

    【讨论】:

      【解决方案4】:

      您可以从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 
      

      【讨论】:

      • 我实际上并不想禁用架构迁移,只想禁用数据迁移。
      【解决方案5】:

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

      我认为您应该检查您的测试是否正在运行,如果答案为 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 []
      

      我又一次注意到,在我看来,这是一个肮脏的 hack,阅读它应该如何以正确的方式制作会很有趣,但这个解决方案可能有助于解决您保存迁移依赖项的问题。 请注意,您还可以在 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)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-10-27
        • 2022-07-22
        • 1970-01-01
        • 1970-01-01
        • 2020-11-17
        • 2012-04-20
        • 2019-09-05
        相关资源
        最近更新 更多