I tried to unit test my Django program and I would like to check several values for a few variables in my settings.py
file.
In the documentation, the section "Overriding settings" is describing a way to do it. But, despite all my attempts, I miserably fail to make the changes available in the program while the test is running. Here is a summary of what I do on a minimal example:
First, create a new project:
$ pyvenv virtualenv
$ cd virtualenv/
$ . bin/activate
(virtualenv) $ pip install django
(virtualenv) $ django-admin startproject myapp
(virtualenv) $ cd myapp/
Then, add the following files.
settings.py
...
TEST_VALUE = 'a'
tests.py
from django.test import TestCase
from myapp.settings import TEST_VALUE
class CheckSettings(TestCase):
def test_settings(self):
self.assertEqual(TEST_VALUE, 'a')
def test_modified_settings(self):
with self.settings(TEST_VALUE='b'):
self.assertEqual(TEST_VALUE, 'b')
When I run the tests, I get the following:
$ ./manage.py test
Creating test database for alias 'default'...
F.
======================================================================
FAIL: test_modified_settings (myapp.tests.CheckSettings)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/virtualenv/myapp/tests.py", line 12, in test_modified_settings
self.assertEqual(TEST_VALUE, 'b')
AssertionError: 'a' != 'b'
----------------------------------------------------------------------
Ran 2 tests in 0.001s
FAILED (failures=1)
Destroying test database for alias 'default'...
As you may have noticed, the original value of TEST_VALUE
is 'a'
, and I try to modify it through the self.settings(TEST_VALUE='b')
... but, without success.
You may try it through an empty project (Django is 1.6.5).
So, what am I missing to get it work properly ?
Just to sum up what I understood from the comment from Ismail Badawi, in fact, I was not calling properly the variable from the settings.py
because I was using from myapp.settings import TEST_VALUE
, where I should have call it using from django.conf import settings
and then settings.TEST_VALUE
.
So, here is a proper tests.py
file:
from django.test import TestCase
from django.conf import settings
class CheckSettings(TestCase):
def test_settings(self):
self.assertEqual(settings.TEST_VALUE, 'a')
def test_modified_settings(self):
with self.settings(TEST_VALUE='b'):
self.assertEqual(settings.TEST_VALUE, 'b')
And, here is the result of ./manage.py test
:
$ ./manage.py test
Creating test database for alias 'default'...
..
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
Destroying test database for alias 'default'...
So, the lesson of this little story is to always get your settings values from django.conf
and not from myapp.settings
when you use it.
Note also that if you are using a cache, some values of your settings.py
may be stored in it and could be masked by their cached value. For that, the documentation of Django on "Overriding settings" gives a hint to solve this kind of problem:
When overriding settings, make sure to handle the cases in which your app’s code uses a cache or similar feature that retains state even if the setting is changed. Django provides the
django.test.signals.setting_changed
signal that lets you register callbacks to clean up and otherwise reset state when settings are changed.
Thought, the way to implement it for real is not given. It could be a good question to ask next...
You should use the @override_settings decorator. https://docs.djangoproject.com/en/1.4/topics/testing/#django.test.utils.override_settings
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With