summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/test/testcases.py33
-rw-r--r--docs/releases/1.8.txt8
-rw-r--r--docs/topics/testing/tools.txt21
-rw-r--r--tests/cache/tests.py5
-rw-r--r--tests/file_uploads/tests.py4
-rw-r--r--tests/mail/tests.py2
-rw-r--r--tests/servers/tests.py15
-rw-r--r--tests/settings_tests/tests.py10
-rw-r--r--tests/utils_tests/test_tzinfo.py2
9 files changed, 73 insertions, 27 deletions
diff --git a/django/test/testcases.py b/django/test/testcases.py
index 566c9395fb..9b25a0b937 100644
--- a/django/test/testcases.py
+++ b/django/test/testcases.py
@@ -161,6 +161,24 @@ class SimpleTestCase(unittest.TestCase):
_overridden_settings = None
_modified_settings = None
+ @classmethod
+ def setUpClass(cls):
+ if cls._overridden_settings:
+ cls._cls_overridden_context = override_settings(**cls._overridden_settings)
+ cls._cls_overridden_context.enable()
+ if cls._modified_settings:
+ cls._cls_modified_context = modify_settings(cls._modified_settings)
+ cls._cls_modified_context.enable()
+
+ @classmethod
+ def tearDownClass(cls):
+ if hasattr(cls, '_cls_modified_context'):
+ cls._cls_modified_context.disable()
+ delattr(cls, '_cls_modified_context')
+ if hasattr(cls, '_cls_overridden_context'):
+ cls._cls_overridden_context.disable()
+ delattr(cls, '_cls_overridden_context')
+
def __call__(self, result=None):
"""
Wrapper around default __call__ method to perform common Django test
@@ -192,24 +210,18 @@ class SimpleTestCase(unittest.TestCase):
* If the class has a 'urls' attribute, replace ROOT_URLCONF with it.
* Clearing the mail test outbox.
"""
- if self._overridden_settings:
- self._overridden_context = override_settings(**self._overridden_settings)
- self._overridden_context.enable()
- if self._modified_settings:
- self._modified_context = modify_settings(self._modified_settings)
- self._modified_context.enable()
self.client = self.client_class()
self._urlconf_setup()
mail.outbox = []
def _urlconf_setup(self):
- set_urlconf(None)
if hasattr(self, 'urls'):
warnings.warn(
"SimpleTestCase.urls is deprecated and will be removed in "
"Django 2.0. Use @override_settings(ROOT_URLCONF=...) "
"in %s instead." % self.__class__.__name__,
RemovedInDjango20Warning, stacklevel=2)
+ set_urlconf(None)
self._old_root_urlconf = settings.ROOT_URLCONF
settings.ROOT_URLCONF = self.urls
clear_url_caches()
@@ -220,14 +232,10 @@ class SimpleTestCase(unittest.TestCase):
* Putting back the original ROOT_URLCONF if it was changed.
"""
self._urlconf_teardown()
- if self._modified_settings:
- self._modified_context.disable()
- if self._overridden_settings:
- self._overridden_context.disable()
def _urlconf_teardown(self):
- set_urlconf(None)
if hasattr(self, '_old_root_urlconf'):
+ set_urlconf(None)
settings.ROOT_URLCONF = self._old_root_urlconf
clear_url_caches()
@@ -1169,6 +1177,7 @@ class LiveServerTestCase(TransactionTestCase):
@classmethod
def setUpClass(cls):
+ super(LiveServerTestCase, cls).setUpClass()
connections_override = {}
for conn in connections.all():
# If using in-memory sqlite databases, pass the connections to
diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt
index 00a2c9844c..875f17f40f 100644
--- a/docs/releases/1.8.txt
+++ b/docs/releases/1.8.txt
@@ -919,3 +919,11 @@ to construct the "view on site" URL. This URL is now accessible using the
``FormMixin`` subclasses that override the ``get_form()`` method should make
sure to provide a default value for the ``form_class`` argument since it's
now optional.
+
+Overriding ``setUpClass`` / ``tearDownClass`` in test cases
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The decorators :func:`~django.test.override_settings` and
+:func:`~django.test.modify_settings` now act at the class level when used as
+class decorators. As a consequence, when overriding ``setUpClass()`` or
+``tearDownClass()``, the ``super`` implementation should always be called.
diff --git a/docs/topics/testing/tools.txt b/docs/topics/testing/tools.txt
index 8049d62761..1ff0d15352 100644
--- a/docs/topics/testing/tools.txt
+++ b/docs/topics/testing/tools.txt
@@ -607,6 +607,25 @@ then you should use :class:`~django.test.TransactionTestCase` or
``SimpleTestCase`` inherits from ``unittest.TestCase``.
+.. warning::
+
+ ``SimpleTestCase`` and its subclasses (e.g. ``TestCase``, ...) rely on
+ ``setUpClass()`` and ``tearDownClass()`` to perform some class-wide
+ initialization (e.g. overriding settings). If you need to override those
+ methods, don't forget to call the ``super`` implementation::
+
+ class MyTestCase(TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ super(cls, MyTestCase).setUpClass() # Call parent first
+ ...
+
+ @classmethod
+ def tearDownClass(cls):
+ ...
+ super(cls, MyTestCase).tearDownClass() # Call parent last
+
TransactionTestCase
~~~~~~~~~~~~~~~~~~~
@@ -751,8 +770,8 @@ Then, add a ``LiveServerTestCase``-based test to your app's tests module
@classmethod
def setUpClass(cls):
- cls.selenium = WebDriver()
super(MySeleniumTests, cls).setUpClass()
+ cls.selenium = WebDriver()
@classmethod
def tearDownClass(cls):
diff --git a/tests/cache/tests.py b/tests/cache/tests.py
index 3ad1979af4..c7604f131e 100644
--- a/tests/cache/tests.py
+++ b/tests/cache/tests.py
@@ -28,6 +28,7 @@ from django.middleware.csrf import CsrfViewMiddleware
from django.template import Template
from django.template.response import TemplateResponse
from django.test import TestCase, TransactionTestCase, RequestFactory, override_settings
+from django.test.signals import setting_changed
from django.test.utils import IgnoreDeprecationWarningsMixin
from django.utils import six
from django.utils import timezone
@@ -1144,8 +1145,12 @@ class FileBasedCacheTests(BaseCacheTests, TestCase):
def setUp(self):
super(FileBasedCacheTests, self).setUp()
self.dirname = tempfile.mkdtemp()
+ # Caches location cannot be modified through override_settings / modify_settings,
+ # hence settings are manipulated directly here and the setting_changed signal
+ # is triggered manually.
for cache_params in settings.CACHES.values():
cache_params.update({'LOCATION': self.dirname})
+ setting_changed.send(self.__class__, setting='CACHES', enter=False)
def tearDown(self):
super(FileBasedCacheTests, self).tearDown()
diff --git a/tests/file_uploads/tests.py b/tests/file_uploads/tests.py
index fe1a79fc9f..4fa75415ec 100644
--- a/tests/file_uploads/tests.py
+++ b/tests/file_uploads/tests.py
@@ -33,12 +33,14 @@ class FileUploadTests(TestCase):
@classmethod
def setUpClass(cls):
+ super(FileUploadTests, cls).setUpClass()
if not os.path.isdir(MEDIA_ROOT):
os.makedirs(MEDIA_ROOT)
@classmethod
def tearDownClass(cls):
shutil.rmtree(MEDIA_ROOT)
+ super(FileUploadTests, cls).tearDownClass()
def test_simple_upload(self):
with open(__file__, 'rb') as fp:
@@ -494,12 +496,14 @@ class DirectoryCreationTests(TestCase):
"""
@classmethod
def setUpClass(cls):
+ super(DirectoryCreationTests, cls).setUpClass()
if not os.path.isdir(MEDIA_ROOT):
os.makedirs(MEDIA_ROOT)
@classmethod
def tearDownClass(cls):
shutil.rmtree(MEDIA_ROOT)
+ super(DirectoryCreationTests, cls).tearDownClass()
def setUp(self):
self.obj = FileModel()
diff --git a/tests/mail/tests.py b/tests/mail/tests.py
index a6184bd767..9431077e06 100644
--- a/tests/mail/tests.py
+++ b/tests/mail/tests.py
@@ -855,6 +855,7 @@ class SMTPBackendTests(BaseEmailBackendTests, SimpleTestCase):
@classmethod
def setUpClass(cls):
+ super(SMTPBackendTests, cls).setUpClass()
cls.server = FakeSMTPServer(('127.0.0.1', 0), None)
cls._settings_override = override_settings(
EMAIL_HOST="127.0.0.1",
@@ -866,6 +867,7 @@ class SMTPBackendTests(BaseEmailBackendTests, SimpleTestCase):
def tearDownClass(cls):
cls._settings_override.disable()
cls.server.stop()
+ super(SMTPBackendTests, cls).tearDownClass()
def setUp(self):
super(SMTPBackendTests, self).setUp()
diff --git a/tests/servers/tests.py b/tests/servers/tests.py
index 2331a0ddce..50b2cafe1a 100644
--- a/tests/servers/tests.py
+++ b/tests/servers/tests.py
@@ -27,7 +27,7 @@ TEST_SETTINGS = {
}
-@override_settings(ROOT_URLCONF='servers.urls')
+@override_settings(ROOT_URLCONF='servers.urls', **TEST_SETTINGS)
class LiveServerBase(LiveServerTestCase):
available_apps = [
@@ -38,19 +38,6 @@ class LiveServerBase(LiveServerTestCase):
]
fixtures = ['testdata.json']
- @classmethod
- def setUpClass(cls):
- # Override settings
- cls.settings_override = override_settings(**TEST_SETTINGS)
- cls.settings_override.enable()
- super(LiveServerBase, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- # Restore original settings
- cls.settings_override.disable()
- super(LiveServerBase, cls).tearDownClass()
-
def urlopen(self, url):
return urlopen(self.live_server_url + url)
diff --git a/tests/settings_tests/tests.py b/tests/settings_tests/tests.py
index c679962a99..64f99fc859 100644
--- a/tests/settings_tests/tests.py
+++ b/tests/settings_tests/tests.py
@@ -106,9 +106,19 @@ class ClassDecoratedTestCaseSuper(TestCase):
@override_settings(TEST='override')
class ClassDecoratedTestCase(ClassDecoratedTestCaseSuper):
+
+ @classmethod
+ def setUpClass(cls):
+ super(cls, ClassDecoratedTestCase).setUpClass()
+ cls.foo = getattr(settings, 'TEST', 'BUG')
+
def test_override(self):
self.assertEqual(settings.TEST, 'override')
+ def test_setupclass_override(self):
+ """Test that settings are overriden within setUpClass -- refs #21281"""
+ self.assertEqual(self.foo, 'override')
+
@override_settings(TEST='override2')
def test_method_override(self):
self.assertEqual(settings.TEST, 'override2')
diff --git a/tests/utils_tests/test_tzinfo.py b/tests/utils_tests/test_tzinfo.py
index 1b007f5f76..4d1af62f0a 100644
--- a/tests/utils_tests/test_tzinfo.py
+++ b/tests/utils_tests/test_tzinfo.py
@@ -20,6 +20,7 @@ class TzinfoTests(IgnoreDeprecationWarningsMixin, unittest.TestCase):
@classmethod
def setUpClass(cls):
+ super(TzinfoTests, cls).setUpClass()
cls.old_TZ = os.environ.get('TZ')
os.environ['TZ'] = 'US/Eastern'
@@ -41,6 +42,7 @@ class TzinfoTests(IgnoreDeprecationWarningsMixin, unittest.TestCase):
# Cleanup - force re-evaluation of TZ environment variable.
if cls.tz_tests:
time.tzset()
+ super(TzinfoTests, cls).tearDownClass()
def test_fixedoffset(self):
self.assertEqual(repr(FixedOffset(0)), '+0000')