Django: override setting used in AppConfig ready function

We are trying to write an automatic test for the behavior of the AppConfig.ready function, which we use as an initialization hook to run the code when loading the Django application. Our implementation of the ready method uses the Django parameter, which we need to override in our test, and, of course, we are trying to use the override_settings decorator to achieve this.

However, there is a problem - when the test is executed, the ready function is executed at the point, the parameter redefinition has not kicked (it still uses the original value from settings.py ). Is there a way in which we can still override the parameter so that the override is applied when calling the ready function?

Some code demonstrating this behavior:

settings.py

 MY_SETTING = 'original value' 

dummy_app / __ __ INIT. RU

 default_app_config = 'dummy_app.apps.DummyAppConfig' 

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)) 

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') 

Output

 ====================================================================== 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 << ---------------------- 

It is important to note that we just want to override this parameter for tests that claim ready behavior, so we don’t consider changing the settings in settings.py or using a separate version of this file that was used only to run our automatic tests.

One of the options considered is that we could simply initialize the AppConfig class in our test, call ready and test the behavior in this way (after which the installation will be overridden by the decorator). However, we would prefer to use this as an integration test and rely on the natural behavior of Django to call the function for us - this is the key functionality for us, and we want to make sure that the test fails if the Django initialization behavior has changed.

+6
source share
1 answer

Some ideas (various efforts and automatic confidence are required):

  • Do not run the integration test and rely on reading release notes / commits before upgrading the Django version and / or rely on one manual test.
  • Assuming that the deployment of the test phase - create the deployment pipeline, unit test special cases in isolation and add an integration test as a smoke test deployment (for example: by displaying this settings value using a control command or an internal single URL endpoint) - just make sure that for of staging, it matters what it should be for staging. Slightly delayed feedback compared to unit tests
  • test it through a test environment outside of Django own - that is: write unittest (or py.test s) and inside these tests bootstrap django in each test (although you need a way to import and manage settings)
  • use a combination of overriding settings through the OS environment (we used envdir a'la 12 factor application ) and a control command that will run the test - for example: MY_SETTING='overridden value' INSTALLED_APPS='dummy_app' EXPECTED_OUTCOME='whatever' python manage.py ensure_app_config_initialized_as_expected
  • looking at Django's own application launch tests apps.clear_cache() and with override_settings(INSTALLED_APPS=['test_app']): config = apps.get_app_config('test_app') assert config.... might work, although I never tried it
+1
source

Source: https://habr.com/ru/post/990055/


All Articles