From def09bf4126d4886413adf7388882eca8e32576b Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Sat, 16 Oct 2021 17:15:50 -0400 Subject: [PATCH] Fixed #27079 -- Avoided multiple setUpClass()/tearDownClass() calls in LiveServerTestCase tests. --- django/test/testcases.py | 17 ++++----- tests/servers/tests.py | 40 ++++++++-------------- tests/staticfiles_tests/test_liveserver.py | 20 ++--------- 3 files changed, 23 insertions(+), 54 deletions(-) diff --git a/django/test/testcases.py b/django/test/testcases.py index 004925e8f7..e65a466ebd 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -1533,7 +1533,11 @@ class LiveServerTestCase(TransactionTestCase): ALLOWED_HOSTS={'append': cls.allowed_host}, ) cls._live_server_modified_settings.enable() + cls.addClassCleanup(cls._live_server_modified_settings.disable) + cls._start_server_thread() + @classmethod + def _start_server_thread(cls): connections_override = cls._make_connections_override() for conn in connections_override.values(): # Explicitly enable thread-shareability for this connection. @@ -1542,13 +1546,11 @@ class LiveServerTestCase(TransactionTestCase): cls.server_thread = cls._create_server_thread(connections_override) cls.server_thread.daemon = True cls.server_thread.start() + cls.addClassCleanup(cls._terminate_thread) # Wait for the live server to be ready cls.server_thread.is_ready.wait() if cls.server_thread.error: - # Clean up behind ourselves, since tearDownClass won't get called in - # case of errors. - cls._tearDownClassInternal() raise cls.server_thread.error @classmethod @@ -1561,20 +1563,13 @@ class LiveServerTestCase(TransactionTestCase): ) @classmethod - def _tearDownClassInternal(cls): + def _terminate_thread(cls): # Terminate the live server's thread. cls.server_thread.terminate() # Restore shared connections' non-shareability. for conn in cls.server_thread.connections_override.values(): conn.dec_thread_sharing() - cls._live_server_modified_settings.disable() - super().tearDownClass() - - @classmethod - def tearDownClass(cls): - cls._tearDownClassInternal() - class SerializeMixin: """ diff --git a/tests/servers/tests.py b/tests/servers/tests.py index cea25b9920..2b2eab20aa 100644 --- a/tests/servers/tests.py +++ b/tests/servers/tests.py @@ -127,18 +127,12 @@ class LiveServerTestCaseSetupTest(LiveServerBase): super().setUpClass() except RuntimeError: # LiveServerTestCase's change to ALLOWED_HOSTS should be reverted. + cls.doClassCleanups() cls.check_allowed_hosts(['testserver']) else: raise RuntimeError('Server did not fail.') cls.set_up_called = True - @classmethod - def tearDownClass(cls): - # Make tearDownClass() a no-op because setUpClass() was already cleaned - # up, and because the error inside setUpClass() was handled, which will - # cause tearDownClass() to be called when it normally wouldn't. - pass - def test_set_up_class(self): self.assertIs(self.set_up_called, True) @@ -334,7 +328,7 @@ class LiveServerPort(LiveServerBase): """ TestCase = type("TestCase", (LiveServerBase,), {}) try: - TestCase.setUpClass() + TestCase._start_server_thread() except OSError as e: if e.errno == errno.EADDRINUSE: # We're out of ports, LiveServerTestCase correctly fails with @@ -342,15 +336,12 @@ class LiveServerPort(LiveServerBase): return # Unexpected error. raise - try: - # We've acquired a port, ensure our server threads acquired - # different addresses. - self.assertNotEqual( - self.live_server_url, TestCase.live_server_url, - "Acquired duplicate server addresses for server threads: %s" % self.live_server_url - ) - finally: - TestCase.tearDownClass() + self.assertNotEqual( + self.live_server_url, + TestCase.live_server_url, + f'Acquired duplicate server addresses for server threads: ' + f'{self.live_server_url}', + ) def test_specified_port_bind(self): """LiveServerTestCase.port customizes the server's port.""" @@ -360,14 +351,13 @@ class LiveServerPort(LiveServerBase): s.bind(('', 0)) TestCase.port = s.getsockname()[1] s.close() - TestCase.setUpClass() - try: - self.assertEqual( - TestCase.port, TestCase.server_thread.port, - 'Did not use specified port for LiveServerTestCase thread: %s' % TestCase.port - ) - finally: - TestCase.tearDownClass() + TestCase._start_server_thread() + self.assertEqual( + TestCase.port, + TestCase.server_thread.port, + f'Did not use specified port for LiveServerTestCase thread: ' + f'{TestCase.port}', + ) class LiveServerThreadedTests(LiveServerBase): diff --git a/tests/staticfiles_tests/test_liveserver.py b/tests/staticfiles_tests/test_liveserver.py index 970121f2da..38d1513c9a 100644 --- a/tests/staticfiles_tests/test_liveserver.py +++ b/tests/staticfiles_tests/test_liveserver.py @@ -29,22 +29,8 @@ class LiveServerBase(StaticLiveServerTestCase): # Override settings cls.settings_override = override_settings(**TEST_SETTINGS) cls.settings_override.enable() - try: - super().setUpClass() - except Exception: - # Clean up since tearDownClass() isn't called on errors. - cls._tearDownLiveServerBase() - raise - - @classmethod - def _tearDownLiveServerBase(cls): - # Restore original settings - cls.settings_override.disable() - - @classmethod - def tearDownClass(cls): - super().tearDownClass() - cls._tearDownLiveServerBase() + cls.addClassCleanup(cls.settings_override.disable) + super().setUpClass() class StaticLiveServerChecks(LiveServerBase): @@ -74,8 +60,6 @@ class StaticLiveServerChecks(LiveServerBase): # app without having set the required STATIC_URL setting.") pass else: - # super().setUpClass() cleans up after itself on a failure. - super().tearDownClass() raise Exception('setUpClass() should have raised an exception.') def test_test_test(self):