diff --git a/django/contrib/admin/tests.py b/django/contrib/admin/tests.py index 25ea230b28b..6487299f9b8 100644 --- a/django/contrib/admin/tests.py +++ b/django/contrib/admin/tests.py @@ -26,13 +26,14 @@ class AdminSeleniumWebDriverTestCase(LiveServerTestCase): except Exception as e: raise SkipTest('Selenium webdriver "%s" not installed or not ' 'operational: %s' % (cls.webdriver_class, str(e))) + # This has to be last to ensure that resources are cleaned up properly! super(AdminSeleniumWebDriverTestCase, cls).setUpClass() @classmethod - def tearDownClass(cls): + def _tearDownClassInternal(cls): if hasattr(cls, 'selenium'): cls.selenium.quit() - super(AdminSeleniumWebDriverTestCase, cls).tearDownClass() + super(AdminSeleniumWebDriverTestCase, cls)._tearDownClassInternal() def wait_until(self, callback, timeout=10): """ diff --git a/django/test/testcases.py b/django/test/testcases.py index b70fea69e20..193acaef800 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -1182,12 +1182,15 @@ class LiveServerTestCase(TransactionTestCase): # 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 super(LiveServerTestCase, cls).setUpClass() @classmethod - def tearDownClass(cls): + def _tearDownClassInternal(cls): # There may not be a 'server_thread' attribute if setUpClass() for some # reasons has raised an exception. if hasattr(cls, 'server_thread'): @@ -1200,4 +1203,7 @@ class LiveServerTestCase(TransactionTestCase): and conn.settings_dict['NAME'] == ':memory:'): conn.allow_thread_sharing = False + @classmethod + def tearDownClass(cls): + cls._tearDownClassInternal() super(LiveServerTestCase, cls).tearDownClass()