]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
python: tests: implement setUpTestData overridable class method
authorRob van der Linde <rob@catalyst.net.nz>
Tue, 26 Sep 2023 08:10:33 +0000 (21:10 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 29 Sep 2023 02:18:34 +0000 (02:18 +0000)
On Python 3.6 and 3.7 the addClassCleanup method needs to be implemented, and tearDownClass must be called by setupClass if any exception is raised.

On Python 3.8 and higher, unittest already calls tearDownClass, even if it raises an exception in setUpClass.

Signed-off-by: Rob van der Linde <rob@catalyst.net.nz>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
python/samba/tests/__init__.py

index 8cb3d13df544187818cd874af871720ba29bba6d..e78115665399e513ec20a60314112e3c067c445a 100644 (file)
@@ -19,6 +19,7 @@
 """Samba Python tests."""
 import os
 import tempfile
+import traceback
 import collections
 import ldb
 import samba
@@ -81,6 +82,59 @@ def DynamicTestCase(cls):
 class TestCase(unittest.TestCase):
     """A Samba test case."""
 
+    # Re-implement addClassCleanup to support Python versions older than 3.8.
+    # Can be removed once these older Python versions are no longer needed.
+    if sys.version_info.major == 3 and sys.version_info.minor < 8:
+        _class_cleanups = []
+
+        @classmethod
+        def addClassCleanup(cls, function, *args, **kwargs):
+            cls._class_cleanups.append((function, args, kwargs))
+
+        @classmethod
+        def tearDownClass(cls):
+            teardown_exceptions = []
+
+            while cls._class_cleanups:
+                function, args, kwargs = cls._class_cleanups.pop()
+                try:
+                    function(*args, **kwargs)
+                except Exception:
+                    teardown_exceptions.append(traceback.format_exc())
+
+            # ExceptionGroup would be better but requires Python 3.11
+            if teardown_exceptions:
+                raise ValueError("tearDownClass failed:\n\n" +
+                                 "\n".join(teardown_exceptions))
+
+        @classmethod
+        def setUpClass(cls):
+            """
+            Call setUpTestData, ensure tearDownClass is called on exceptions.
+
+            This is only required on Python versions older than 3.8.
+            """
+            try:
+                cls.setUpTestData()
+            except Exception:
+                cls.tearDownClass()
+                raise
+    else:
+        @classmethod
+        def setUpClass(cls):
+            """
+            setUpClass only needs to call setUpTestData.
+
+            On Python 3.8 and above unittest will always call tearDownClass,
+            even if an exception was raised in setUpClass.
+            """
+            cls.setUpTestData()
+
+    @classmethod
+    def setUpTestData(cls):
+        """Create class level test fixtures here."""
+        pass
+
     @classmethod
     def generate_dynamic_test(cls, fnname, suffix, *args, doc=None):
         """