Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added TestCase.settings context manager to easily override settings i…

…n test methods.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16165 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 0dc6420b3ebddd7bc2a0059b225d54ac19d4d901 1 parent 21027a0
Jannis Leidel authored May 06, 2011
19  django/test/testcases.py
@@ -2,11 +2,12 @@
2 2
 
3 3
 import re
4 4
 import sys
  5
+from contextlib import contextmanager
5 6
 from functools import wraps
6 7
 from urlparse import urlsplit, urlunsplit
7 8
 from xml.dom.minidom import parseString, Node
8 9
 
9  
-from django.conf import settings
  10
+from django.conf import settings, UserSettingsHolder
10 11
 from django.core import mail
11 12
 from django.core.management import call_command
12 13
 from django.core.signals import request_started
@@ -341,6 +342,22 @@ def restore_warnings_state(self):
341 342
         """
342 343
         restore_warnings_state(self._warnings_state)
343 344
 
  345
+    @contextmanager
  346
+    def settings(self, **options):
  347
+        """
  348
+        A context manager that temporarily sets a setting and reverts
  349
+        back to the original value when exiting the context.
  350
+        """
  351
+        old_wrapped = settings._wrapped
  352
+        override = UserSettingsHolder(settings._wrapped)
  353
+        try:
  354
+            for key, new_value in options.items():
  355
+                setattr(override, key, new_value)
  356
+            settings._wrapped = override
  357
+            yield
  358
+        finally:
  359
+            settings._wrapped = old_wrapped
  360
+
344 361
     def assertRedirects(self, response, expected_url, status_code=302,
345 362
                         target_status_code=200, host=None, msg_prefix=''):
346 363
         """Asserts that a response redirected to a specific URL, and that the
25  docs/topics/testing.txt
@@ -1351,6 +1351,31 @@ For example::
1351 1351
 This test case will flush *all* the test databases before running
1352 1352
 ``testIndexPageView``.
1353 1353
 
  1354
+Overriding settings
  1355
+~~~~~~~~~~~~~~~~~~~
  1356
+
  1357
+.. method:: TestCase.settings
  1358
+
  1359
+.. versionadded:: 1.4
  1360
+
  1361
+For testing purposes it's often useful to change a setting temporarily
  1362
+and revert to the original value after running the testing code. For
  1363
+this use case Django provides a standard `Python context manager`_
  1364
+:meth:`~django.test.TestCase.settings`, which can be used like this::
  1365
+
  1366
+    from django.test import TestCase
  1367
+
  1368
+    class LoginTestCase(TestCase):
  1369
+        def test_overriding_settings(self):
  1370
+            with self.settings(LOGIN_URL='/other/login/'):
  1371
+                response = self.client.get('/sekrit/')
  1372
+                self.assertRedirects(response, '/other/login/?next=/sekrit/')
  1373
+
  1374
+This example will override the :setting:`LOGIN_URL` setting for the code
  1375
+in the ``with`` block and reset its value to the previous state afterwards.
  1376
+
  1377
+.. _`Python context manager`: http://www.python.org/dev/peps/pep-0343/
  1378
+
1354 1379
 Emptying the test outbox
1355 1380
 ~~~~~~~~~~~~~~~~~~~~~~~~
1356 1381
 
30  tests/regressiontests/settings_tests/tests.py
... ...
@@ -1,8 +1,31 @@
1 1
 from django.conf import settings
2  
-from django.utils import unittest
  2
+from django.test import TestCase
3 3
 
  4
+class SettingsTests(TestCase):
4 5
 
5  
-class SettingsTests(unittest.TestCase):
  6
+    def test_override(self):
  7
+        settings.TEST = 'test'
  8
+        self.assertEqual('test', settings.TEST)
  9
+        with self.settings(TEST='override'):
  10
+            self.assertEqual('override', settings.TEST)
  11
+        self.assertEqual('test', settings.TEST)
  12
+        del settings.TEST
  13
+
  14
+    def test_override_change(self):
  15
+        settings.TEST = 'test'
  16
+        self.assertEqual('test', settings.TEST)
  17
+        with self.settings(TEST='override'):
  18
+            self.assertEqual('override', settings.TEST)
  19
+            settings.TEST = 'test2'
  20
+        self.assertEqual('test', settings.TEST)
  21
+        del settings.TEST
  22
+
  23
+    def test_override_doesnt_leak(self):
  24
+        self.assertRaises(AttributeError, getattr, settings, 'TEST')
  25
+        with self.settings(TEST='override'):
  26
+            self.assertEqual('override', settings.TEST)
  27
+            settings.TEST = 'test'
  28
+        self.assertRaises(AttributeError, getattr, settings, 'TEST')
6 29
 
7 30
     #
8 31
     # Regression tests for #10130: deleting settings.
@@ -18,7 +41,8 @@ def test_settings_delete_wrapped(self):
18 41
         self.assertRaises(TypeError, delattr, settings, '_wrapped')
19 42
 
20 43
 
21  
-class TrailingSlashURLTests(unittest.TestCase):
  44
+
  45
+class TrailingSlashURLTests(TestCase):
22 46
     settings_module = settings
23 47
 
24 48
     def setUp(self):

0 notes on commit 0dc6420

Please sign in to comment.
Something went wrong with that request. Please try again.