Django:AppConfig就绪功能中使用的覆盖设置

rob*_*cox 9 python django unit-testing startup

我们正在尝试为AppConfig.ready函数的行为编写一个自动化测试,我们将其用作Django应用程序加载时运行代码的初始化挂钩.我们的ready方法实现使用我们需要在测试中覆盖的Django设置,当然我们正在尝试使用override_settings装饰器来实现这一点.

但是有一个障碍 - 当测试运行时,在ready执行该功能的时候,设置覆盖没有启动(它仍然使用原始值settings.py).是否有一种方法可以在ready调用函数时以覆盖方式应用的方式覆盖设置?

一些代码来演示此行为:

settings.py

MY_SETTING = 'original value'
Run Code Online (Sandbox Code Playgroud)

dummy_app/__ init__.py

default_app_config = 'dummy_app.apps.DummyAppConfig'
Run Code Online (Sandbox Code Playgroud)

dummy_app/apps.py

from django.apps import AppConfig
from django.conf import settings


class DummyAppConfig(AppConfig):
    name = 'dummy_app'

    def ready(self):
        print('settings.MY_SETTING in app config ready function: {0}'.format(settings.MY_SETTING))
Run Code Online (Sandbox Code Playgroud)

dummy_app/tests.py

from django.conf import settings
from django.test import TestCase
from django.test.utils import override_settings


@override_settings(MY_SETTING='overridden value')
@override_settings(INSTALLED_APPS=('dummy_app',))
class AppConfigTests(TestCase):

    def test_to_see_where_overridden_settings_value_is_available(self):
        print('settings.MY_SETTING in test function: '.format(settings.MY_SETTING))
        self.fail('Trigger test output')
Run Code Online (Sandbox Code Playgroud)

产量

======================================================================
FAIL: test_to_see_where_overridden_settings_value_is_available (dummy_app.tests.AppConfigTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/labminds/venv/labos/src/dom-base/dummy_app/tests.py", line 12, in test_to_see_where_overridden_settings_value_is_available
    self.fail('Trigger test output')
AssertionError: Trigger test output
-------------------- >> begin captured stdout << ---------------------
settings.MY_SETTING in app config ready function: original value
settings.MY_SETTING in test function: overridden value

--------------------- >> end captured stdout << ----------------------
Run Code Online (Sandbox Code Playgroud)

重要的是要注意,我们只想为断言行为的测试覆盖此设置ready,这就是为什么我们不考虑更改设置settings.py,或者使用仅用于运行我们的自动化的单独版本的文件试验.

已经考虑过一个选项 - 我们可以简单地AppConfig在测试中初始化类,调用ready并测试行为(此时设置将被装饰器覆盖).但是,我们更喜欢将其作为集成测试运行,并依赖Django的自然行为来为我们调用函数 - 这对我们来说是关键功能,我们希望确保在Django的初始化行为发生变化时测试失败.

zse*_*epi 2

一些想法(需要不同的努力和自动化保证):

  • 不要进行集成测试,并在升级 Django 版本之前依赖阅读发行说明/提交和/或依赖单个手动测试
  • 假设测试 - 阶段部署 - 产品部署管道,单独测试特殊情况,并添加集成检查作为部署冒烟测试(例如:通过管理命令或仅限内部的 url 端点公开此设置值) - 仅验证对于分期来说,它具有应有的价值。与单元测试相比,反馈略有延迟
  • 通过 Django 自己的测试框架之外的测试框架进行测试 - 即:编写unittests (或py.tests),并在每个测试中在这些测试中引导 django(尽管您需要一种方法来导入和操作设置)
  • 通过操作系统环境使用覆盖设置的组合(我们使用了envdir a'la 12 Factor app)和执行测试的管理命令 - 例如:MY_SETTING='overridden value' INSTALLED_APPS='dummy_app' EXPECTED_OUTCOME='whatever' python manage.py ensure_app_config_initialized_as_expected
  • 查看Django 自己的应用程序初始化测试 apps.clear_cache()并且 with override_settings(INSTALLED_APPS=['test_app']): config = apps.get_app_config('test_app') assert config.... 可以工作,尽管我从未尝试过