Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying Django settings in tests

From Django docs:

You shouldn’t alter settings in your applications at runtime. For example, don’t do this in a view:

from django.conf import settings

settings.DEBUG = True   # Don't do this!

The only place you should assign to settings is in a settings file.

I've noticed that Django testing code does alter settings. Why is it ok to do it there?

like image 468
planetp Avatar asked Mar 08 '23 06:03

planetp


2 Answers

Is it ok to change settings?

Short answer: No, unless you do it during the startup.

Long answer: Django docs are correct, you should not modify settings at runtime. This means, no settings modifications after the app has been started, like changing configuration in views.py, serializers.py, models.py or other modules you add during the development. But it is ok to modify settings if they depend on local variables if you do it at startup and you are fully aware of what happens.

Can you modify settings while testing?

Yes, if you think you need it. Feel free to rely on override_settings to change settings value for testing purposes in the unit tests, see example of usage here Also, everything that this decorator does - is overriding settings with provided values and restoring settings value after test has passed (decorated function executed).

Why Django does modify them while testing the code.

From what I see, they change settings only for testing purposes and the only thing they do - adding a local host to allowed host so they can test the code using a local domain. Examples like that seem pretty reasonable for me as change is done only once and during unit tests set up. Imagine having overrride_settings call every time, that would be monstrous.

General recommendation.

Try not to, there is no need to modify settings and if there is - think about it, maybe settings is not the right place for a mutable setting? If you want to modify settings at runtime - please be aware that settings might be cached somewhere, copied and accessed all over the place - this is a plenty of space for new bugs. There is nothing bad in it, except having an unexpected behavior of the system due to an old/new value of the modified setting.

Hope this makes sense.

like image 90
taras Avatar answered Mar 30 '23 19:03

taras


The answer is in the wording:

You shouldn’t alter settings in your applications at runtime.

Unit test code is not part of your application, so that statement doesn't apply to unit tests.

Why is it ok to do it there?

As per above, it is perfectly OK to override settings during tests, provided you do it in a localised manner (because tests are sometimes run in a multi-threaded manner).

Here is how they recommend doing it:

from django.test import TestCase

class LoginTestCase(TestCase):

    def test_login(self):

         # First check for the default behavior
         response = self.client.get('/sekrit/')
         self.assertRedirects(response, '/accounts/login/?next=/sekrit/')

         # Then override the LOGIN_URL setting
         with self.settings(LOGIN_URL='/other/login/'):
             response = self.client.get('/sekrit/')
             self.assertRedirects(response, '/other/login/?next=/sekrit/')

See docs: https://docs.djangoproject.com/en/2.2/topics/testing/tools/#django.test.SimpleTestCase.settings

like image 40
andyhasit Avatar answered Mar 30 '23 20:03

andyhasit