I have a whole bunch of test helper functions that take a test instance and use addCleanup to cleanly setup / tear down threads, temp files etc, so I needed the addCleanup API to work for class level fixtures too. I reimplemented a bit of the unittest doCleanup functionality to help me, and used mock to patch addCleanup() during class setup
import unittest
import logging
import mock
LOGGER = logging.getLogger(__name__)
class ClassCleanupTestCase(unittest.TestCase):
_class_cleanups = []
@classmethod
def setUpClassWithCleanup(cls):
def cleanup_fn():
"""Do some cleanup!"""
# Do something that requires cleanup
cls.addCleanup(cleanup_fn)
@classmethod
def addCleanupClass(cls, function, *args, **kwargs):
cls._class_cleanups.append((function, args, kwargs))
@classmethod
def doCleanupsClass(cls):
results = []
while cls._class_cleanups:
function, args, kwargs = cls._class_cleanups.pop()
try:
function(*args, **kwargs)
except Exceptions:
LOGGER.exception('Exception calling class cleanup function')
results.append(sys.exc_info())
if results:
LOGGER.error('Exception(s) raised during class cleanup, re-raising '
'first exception.')
raise results[0]
@classmethod
def setUpClass(cls):
try:
with mock.patch.object(cls, 'addCleanup') as cls_addCleanup:
cls_addCleanup.side_effect = cls.addCleanupClass
cls.setUpClassWithCleanup()
except Exception:
cls.doCleanupsClass()
raise
@classmethod
def tearDownClass(cls):
cls.doCleanupsClass()
addClassCleanup()
andaddModuleCleanup()
as of python 3.8 – Ligamentous