Monday, November 28, 2016

Fixing "Address in use" errors when using StaticLiveServerTestCase subclasses whose setUpClass() fails

I have observed that if I have a subclass of StaticLiveServerTestCase that raises an exception in its custom setUpClass() method then the tearDownClass() method will not be called. Consequently the LiveServerThread will not be cleaned up properly, causing all following StaticLiveServerTestCases in the test run to fail with "Address in use" errors.

Because of this behavior, any StaticLiveServerTestCase with a tearDownClass() method that fails causes a *catastrophic* failure of ALL following StaticLiveServerTestCases in the test suite, which generates a bunch of noisy output that is time consuming to investigate. It would be ideal if a failure of StaticLiveServerTestCase.tearDownClass() caused only a failure of that suite and not all subsequent suites.

Had anyone else run into this issue? What did you do to get a better behavior?

---

Here my own stab at a workaround: Instead of inheriting from StaticLiveServerTestCase directly, I would create a new subclass with an improved behavior:

class SaferStaticLiveServerTestCase(StaticLiveServerTestCase):
    @classmethod
    def setUpClass(cls):
        try:
            super().setUpClass()
            cls.setUpClassAlways()
        except:
            super().tearDownClass()
            cls.tearDownClassAlways()
            raise
    
    @classmethod
    def tearDownClass(cls):
        super().tearDownClass()
        cls.tearDownClassAlways()
        cls.tearDownClassIfSetUp()

    @classmethod
    def setUpClassAlways(cls):
        pass
    
    @classmethod
    def tearDownClassAlways(cls):
        pass
    
    @classmethod
    def tearDownClassIfSetUp(cls):
        pass

Subclasses would override {setUpClassAlways, tearDownClassAlways, tearDownClassIfSetUp} in preference to overriding {setUpClass, tearDownClass} directly.

tearDownClassAlways() is always called after setUpClassAlways() even if it fails. tearDownClassIfSetUp() is called after setUpClassAlways() iff it did not raise an exception.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/3a6710af-0923-467e-a674-d184c623ed31%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment