Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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
@jezdez jezdez authored
View
19 django/test/testcases.py
@@ -2,11 +2,12 @@
import re
import sys
+from contextlib import contextmanager
from functools import wraps
from urlparse import urlsplit, urlunsplit
from xml.dom.minidom import parseString, Node
-from django.conf import settings
+from django.conf import settings, UserSettingsHolder
from django.core import mail
from django.core.management import call_command
from django.core.signals import request_started
@@ -341,6 +342,22 @@ def restore_warnings_state(self):
"""
restore_warnings_state(self._warnings_state)
+ @contextmanager
+ def settings(self, **options):
+ """
+ A context manager that temporarily sets a setting and reverts
+ back to the original value when exiting the context.
+ """
+ old_wrapped = settings._wrapped
+ override = UserSettingsHolder(settings._wrapped)
+ try:
+ for key, new_value in options.items():
+ setattr(override, key, new_value)
+ settings._wrapped = override
+ yield
+ finally:
+ settings._wrapped = old_wrapped
+
def assertRedirects(self, response, expected_url, status_code=302,
target_status_code=200, host=None, msg_prefix=''):
"""Asserts that a response redirected to a specific URL, and that the
View
25 docs/topics/testing.txt
@@ -1351,6 +1351,31 @@ For example::
This test case will flush *all* the test databases before running
``testIndexPageView``.
+Overriding settings
+~~~~~~~~~~~~~~~~~~~
+
+.. method:: TestCase.settings
+
+.. versionadded:: 1.4
+
+For testing purposes it's often useful to change a setting temporarily
+and revert to the original value after running the testing code. For
+this use case Django provides a standard `Python context manager`_
+:meth:`~django.test.TestCase.settings`, which can be used like this::
+
+ from django.test import TestCase
+
+ class LoginTestCase(TestCase):
+ def test_overriding_settings(self):
+ with self.settings(LOGIN_URL='/other/login/'):
+ response = self.client.get('/sekrit/')
+ self.assertRedirects(response, '/other/login/?next=/sekrit/')
+
+This example will override the :setting:`LOGIN_URL` setting for the code
+in the ``with`` block and reset its value to the previous state afterwards.
+
+.. _`Python context manager`: http://www.python.org/dev/peps/pep-0343/
+
Emptying the test outbox
~~~~~~~~~~~~~~~~~~~~~~~~
View
30 tests/regressiontests/settings_tests/tests.py
@@ -1,8 +1,31 @@
from django.conf import settings
-from django.utils import unittest
+from django.test import TestCase
+class SettingsTests(TestCase):
-class SettingsTests(unittest.TestCase):
+ def test_override(self):
+ settings.TEST = 'test'
+ self.assertEqual('test', settings.TEST)
+ with self.settings(TEST='override'):
+ self.assertEqual('override', settings.TEST)
+ self.assertEqual('test', settings.TEST)
+ del settings.TEST
+
+ def test_override_change(self):
+ settings.TEST = 'test'
+ self.assertEqual('test', settings.TEST)
+ with self.settings(TEST='override'):
+ self.assertEqual('override', settings.TEST)
+ settings.TEST = 'test2'
+ self.assertEqual('test', settings.TEST)
+ del settings.TEST
+
+ def test_override_doesnt_leak(self):
+ self.assertRaises(AttributeError, getattr, settings, 'TEST')
+ with self.settings(TEST='override'):
+ self.assertEqual('override', settings.TEST)
+ settings.TEST = 'test'
+ self.assertRaises(AttributeError, getattr, settings, 'TEST')
#
# Regression tests for #10130: deleting settings.
@@ -18,7 +41,8 @@ def test_settings_delete_wrapped(self):
self.assertRaises(TypeError, delattr, settings, '_wrapped')
-class TrailingSlashURLTests(unittest.TestCase):
+
+class TrailingSlashURLTests(TestCase):
settings_module = settings
def setUp(self):
Please sign in to comment.
Something went wrong with that request. Please try again.