mirror of https://github.com/django/django.git
Fixed #31944 -- Used addCleanup() to register TestContextDecorator cleanups.
Cleanups from addCleanup() are scheduled to happen in reverse order to the order they are added (LIFO). Ensures each cleanup is executed from the innermost to the outermost.
This commit is contained in:
parent
11ebc6479f
commit
57dadfac3c
|
@ -351,24 +351,15 @@ class TestContextDecorator:
|
|||
def decorate_class(self, cls):
|
||||
if issubclass(cls, TestCase):
|
||||
decorated_setUp = cls.setUp
|
||||
decorated_tearDown = cls.tearDown
|
||||
|
||||
def setUp(inner_self):
|
||||
context = self.enable()
|
||||
inner_self.addCleanup(self.disable)
|
||||
if self.attr_name:
|
||||
setattr(inner_self, self.attr_name, context)
|
||||
try:
|
||||
decorated_setUp(inner_self)
|
||||
except Exception:
|
||||
self.disable()
|
||||
raise
|
||||
|
||||
def tearDown(inner_self):
|
||||
decorated_tearDown(inner_self)
|
||||
self.disable()
|
||||
decorated_setUp(inner_self)
|
||||
|
||||
cls.setUp = setUp
|
||||
cls.tearDown = tearDown
|
||||
return cls
|
||||
raise TypeError('Can only decorate subclasses of unittest.TestCase')
|
||||
|
||||
|
|
|
@ -484,6 +484,11 @@ Miscellaneous
|
|||
* The undocumented ``django.utils.http.limited_parse_qsl()`` function is
|
||||
removed. Please use :func:`urllib.parse.parse_qsl` instead.
|
||||
|
||||
* ``django.test.utils.TestContextDecorator`` now uses
|
||||
:py:meth:`~unittest.TestCase.addCleanup` so that cleanups registered in the
|
||||
:py:meth:`~unittest.TestCase.setUp` method are called before
|
||||
``TestContextDecorator.disable()``.
|
||||
|
||||
.. _deprecated-features-3.2:
|
||||
|
||||
Features deprecated in 3.2
|
||||
|
|
|
@ -1477,4 +1477,27 @@ class TestContextDecoratorTests(SimpleTestCase):
|
|||
self.assertFalse(mock_disable.called)
|
||||
with self.assertRaisesMessage(NotImplementedError, 'reraised'):
|
||||
decorated_test_class.setUp()
|
||||
decorated_test_class.doCleanups()
|
||||
self.assertTrue(mock_disable.called)
|
||||
|
||||
def test_cleanups_run_after_tearDown(self):
|
||||
calls = []
|
||||
|
||||
class SaveCallsDecorator(TestContextDecorator):
|
||||
def enable(self):
|
||||
calls.append('enable')
|
||||
|
||||
def disable(self):
|
||||
calls.append('disable')
|
||||
|
||||
class AddCleanupInSetUp(unittest.TestCase):
|
||||
def setUp(self):
|
||||
calls.append('setUp')
|
||||
self.addCleanup(lambda: calls.append('cleanup'))
|
||||
|
||||
decorator = SaveCallsDecorator()
|
||||
decorated_test_class = decorator.__call__(AddCleanupInSetUp)()
|
||||
decorated_test_class.setUp()
|
||||
decorated_test_class.tearDown()
|
||||
decorated_test_class.doCleanups()
|
||||
self.assertEqual(calls, ['enable', 'setUp', 'cleanup', 'disable'])
|
||||
|
|
Loading…
Reference in New Issue