Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

[1.6.x] Final attempt to solve sporadic test failures.

tearDownClass is not called if setUpClass throws an exception, in our case
this means that LiveServerTestCase leaks LiveServerThread sockets if the
test happens to be skipped later on, and AdminSeleniumWebDriverTestCase
doesn't close it's already open browser window. To prevent this leakage
we catch errors where needed and manually call _tearDownClassInternal.
_tearDownClassInternal should be written as defensively as possible since
it is not allowed to make any assumptions on how far setUpClass got.

This patch should fix the sporadic "Address already in use"-errors on jenkins
and also the "This code isn't under transaction management"-error for sqlite
(also just on jenkins).

After discussion with koniiiik, jezdez, kmtracey, tos9, lifeless, nedbat and
voidspace it was decided that this is the safest approach (thanks to everyone
for their comments and help). Manually calling tearDownClass was shut down
cause we don't know how our users override our classes.

This is a private and very specialized API on purpose and should not be used
without a strong reason!

This patch partially reverts the earlier attempts to fix those issues,
namely:
	2fa0dd7 and
	3c5775d

Final note: If this patch breaks in a later version of Django, please be
very careful on how you fix it, you might not see test failures locally.
That said, this patch hopefully doesn't produce even more failures.

Backport of 73a610d from master.
  • Loading branch information...
commit 325b03ea844dda21557a2779d6f7e35950174962 1 parent 5937f29
Florian Apolloner authored September 17, 2013
5  django/contrib/admin/tests.py
@@ -26,13 +26,14 @@ def setUpClass(cls):
26 26
         except Exception as e:
27 27
             raise SkipTest('Selenium webdriver "%s" not installed or not '
28 28
                            'operational: %s' % (cls.webdriver_class, str(e)))
  29
+        # This has to be last to ensure that resources are cleaned up properly!
29 30
         super(AdminSeleniumWebDriverTestCase, cls).setUpClass()
30 31
 
31 32
     @classmethod
32  
-    def tearDownClass(cls):
  33
+    def _tearDownClassInternal(cls):
33 34
         if hasattr(cls, 'selenium'):
34 35
             cls.selenium.quit()
35  
-        super(AdminSeleniumWebDriverTestCase, cls).tearDownClass()
  36
+        super(AdminSeleniumWebDriverTestCase, cls)._tearDownClassInternal()
36 37
 
37 38
     def wait_until(self, callback, timeout=10):
38 39
         """
8  django/test/testcases.py
@@ -1182,12 +1182,15 @@ def setUpClass(cls):
1182 1182
         # Wait for the live server to be ready
1183 1183
         cls.server_thread.is_ready.wait()
1184 1184
         if cls.server_thread.error:
  1185
+            # Clean up behind ourselves, since tearDownClass won't get called in
  1186
+            # case of errors.
  1187
+            cls._tearDownClassInternal()
1185 1188
             raise cls.server_thread.error
1186 1189
 
1187 1190
         super(LiveServerTestCase, cls).setUpClass()
1188 1191
 
1189 1192
     @classmethod
1190  
-    def tearDownClass(cls):
  1193
+    def _tearDownClassInternal(cls):
1191 1194
         # There may not be a 'server_thread' attribute if setUpClass() for some
1192 1195
         # reasons has raised an exception.
1193 1196
         if hasattr(cls, 'server_thread'):
@@ -1200,4 +1203,7 @@ def tearDownClass(cls):
1200 1203
                 and conn.settings_dict['NAME'] == ':memory:'):
1201 1204
                 conn.allow_thread_sharing = False
1202 1205
 
  1206
+    @classmethod
  1207
+    def tearDownClass(cls):
  1208
+        cls._tearDownClassInternal()
1203 1209
         super(LiveServerTestCase, cls).tearDownClass()

0 notes on commit 325b03e

Please sign in to comment.
Something went wrong with that request. Please try again.