Commit d89f56dc authored by Thomas Chaumeny's avatar Thomas Chaumeny Committed by Tim Graham
Browse files

Fixed #21281 -- Made override_settings act at class level when used as a TestCase decorator.

parent 8b77b64f
Loading
Loading
Loading
Loading
+21 −12
Original line number Diff line number Diff line
@@ -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
+8 −0
Original line number Diff line number Diff line
@@ -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.
+20 −1
Original line number Diff line number Diff line
@@ -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):
+5 −0
Original line number Diff line number Diff line
@@ -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()
+4 −0
Original line number Diff line number Diff line
@@ -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()
Loading