Is there any simple mechanism for overriding Django settings for a unit test? I have a manager on one of my models that returns a specific number of the latest objects. The number of objects it returns is defined by a NUM_LATEST setting.
This has the potential to make my tests fail if someone were to change the setting. How can I override the settings on setUp()
and subsequently restore them on tearDown()
? If that isn't possible, is there some way I can monkey patch the method or mock the settings?
EDIT: Here is my manager code:
class LatestManager(models.Manager): """ Returns a specific number of the most recent public Articles as defined by the NEWS_LATEST_MAX setting. """ def get_query_set(self): num_latest = getattr(settings, 'NEWS_NUM_LATEST', 10) return super(LatestManager, self).get_query_set().filter(is_public=True)[:num_latest]
The manager uses settings.NEWS_LATEST_MAX
to slice the queryset. The getattr()
is simply used to provide a default should the setting not exist.
To write a test you derive from any of the Django (or unittest) test base classes (SimpleTestCase, TransactionTestCase, TestCase, LiveServerTestCase) and then write separate methods to check that specific functionality works as expected (tests use "assert" methods to test that expressions result in True or False values ...
Default settings These defaults live in the module django/conf/global_settings.py . Here's the algorithm Django uses in compiling settings: Load settings from global_settings.py . Load settings from the specified settings file, overriding the global settings as necessary.
Which is better – pytest or unittest? Although both the frameworks are great for performing testing in python, pytest is easier to work with. The code in pytest is simple, compact, and efficient. For unittest, we will have to import modules, create a class and define the testing functions within that class.
EDIT: This answer applies if you want to change settings for a small number of specific tests.
Since Django 1.4, there are ways to override settings during tests: https://docs.djangoproject.com/en/stable/topics/testing/tools/#overriding-settings
TestCase
will have a self.settings
context manager, and there will also be an @override_settings
decorator that can be applied to either a test method or a whole TestCase
subclass.
These features did not exist yet in Django 1.3.
If you want to change settings for all your tests, you'll want to create a separate settings file for test, which can load and override settings from your main settings file. There are several good approaches to this in the other answers; I have seen successful variations on both hspander's and dmitrii's approaches.
You can do anything you like to the UnitTest
subclass, including setting and reading instance properties:
from django.conf import settings class MyTest(unittest.TestCase): def setUp(self): self.old_setting = settings.NUM_LATEST settings.NUM_LATEST = 5 # value tested against in the TestCase def tearDown(self): settings.NUM_LATEST = self.old_setting
Since the django test cases run single-threaded, however, I'm curious about what else may be modifying the NUM_LATEST value? If that "something else" is triggered by your test routine, then I'm not sure any amount of monkey patching will save the test without invalidating the veracity of the tests itself.
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