bpo-24412: Adds cleanUps for setUpClass and setUpModule. (GH-9190)
This commit is contained in:
parent
49fa4a9f1e
commit
0f221d09ca
|
@ -1448,6 +1448,39 @@ Test cases
|
||||||
|
|
||||||
.. versionadded:: 3.1
|
.. versionadded:: 3.1
|
||||||
|
|
||||||
|
.. classmethod:: addClassCleanup(function, *args, **kwargs)
|
||||||
|
|
||||||
|
Add a function to be called after :meth:`tearDownClass` to cleanup
|
||||||
|
resources used during the test class. Functions will be called in reverse
|
||||||
|
order to the order they are added (:abbr:`LIFO (last-in, first-out)`).
|
||||||
|
They are called with any arguments and keyword arguments passed into
|
||||||
|
:meth:`addClassCleanup` when they are added.
|
||||||
|
|
||||||
|
If :meth:`setUpClass` fails, meaning that :meth:`tearDownClass` is not
|
||||||
|
called, then any cleanup functions added will still be called.
|
||||||
|
|
||||||
|
.. versionadded:: 3.8
|
||||||
|
|
||||||
|
|
||||||
|
.. classmethod:: doClassCleanups()
|
||||||
|
|
||||||
|
This method is called unconditionally after :meth:`tearDownClass`, or
|
||||||
|
after :meth:`setUpClass` if :meth:`setUpClass` raises an exception.
|
||||||
|
|
||||||
|
It is responsible for calling all the cleanup functions added by
|
||||||
|
:meth:`addCleanupClass`. If you need cleanup functions to be called
|
||||||
|
*prior* to :meth:`tearDownClass` then you can call
|
||||||
|
:meth:`doCleanupsClass` yourself.
|
||||||
|
|
||||||
|
:meth:`doCleanupsClass` pops methods off the stack of cleanup
|
||||||
|
functions one at a time, so it can be called at any time.
|
||||||
|
|
||||||
|
.. versionadded:: 3.8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. class:: FunctionTestCase(testFunc, setUp=None, tearDown=None, description=None)
|
.. class:: FunctionTestCase(testFunc, setUp=None, tearDown=None, description=None)
|
||||||
|
|
||||||
|
@ -2268,6 +2301,38 @@ module will be run and the ``tearDownModule`` will not be run. If the exception
|
||||||
:exc:`SkipTest` exception then the module will be reported as having been skipped
|
:exc:`SkipTest` exception then the module will be reported as having been skipped
|
||||||
instead of as an error.
|
instead of as an error.
|
||||||
|
|
||||||
|
To add cleanup code that must be run even in the case of an exception, use
|
||||||
|
``addModuleCleanup``:
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: addModuleCleanup(function, *args, **kwargs)
|
||||||
|
|
||||||
|
Add a function to be called after :func:`tearDownModule` to cleanup
|
||||||
|
resources used during the test class. Functions will be called in reverse
|
||||||
|
order to the order they are added (:abbr:`LIFO (last-in, first-out)`).
|
||||||
|
They are called with any arguments and keyword arguments passed into
|
||||||
|
:meth:`addModuleCleanup` when they are added.
|
||||||
|
|
||||||
|
If :meth:`setUpModule` fails, meaning that :func:`tearDownModule` is not
|
||||||
|
called, then any cleanup functions added will still be called.
|
||||||
|
|
||||||
|
.. versionadded:: 3.8
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: doModuleCleanups()
|
||||||
|
|
||||||
|
This function is called unconditionally after :func:`tearDownModule`, or
|
||||||
|
after :func:`setUpModule` if :func:`setUpModule` raises an exception.
|
||||||
|
|
||||||
|
It is responsible for calling all the cleanup functions added by
|
||||||
|
:func:`addCleanupModule`. If you need cleanup functions to be called
|
||||||
|
*prior* to :func:`tearDownModule` then you can call
|
||||||
|
:func:`doModuleCleanups` yourself.
|
||||||
|
|
||||||
|
:func:`doModuleCleanups` pops methods off the stack of cleanup
|
||||||
|
functions one at a time, so it can be called at any time.
|
||||||
|
|
||||||
|
.. versionadded:: 3.8
|
||||||
|
|
||||||
Signal Handling
|
Signal Handling
|
||||||
---------------
|
---------------
|
||||||
|
|
|
@ -233,6 +233,15 @@ unicodedata
|
||||||
is in a specific normal form. (Contributed by Max Belanger and David Euresti in
|
is in a specific normal form. (Contributed by Max Belanger and David Euresti in
|
||||||
:issue:`32285`).
|
:issue:`32285`).
|
||||||
|
|
||||||
|
unittest
|
||||||
|
--------
|
||||||
|
|
||||||
|
* Added :func:`~unittest.addModuleCleanup()` and
|
||||||
|
:meth:`~unittest.TestCase.addClassCleanup()` to unittest to support
|
||||||
|
cleanups for :func:`~unittest.setUpModule()` and
|
||||||
|
:meth:`~unittest.TestCase.setUpClass()`.
|
||||||
|
(Contributed by Lisa Roach in :issue:`24412`.)
|
||||||
|
|
||||||
venv
|
venv
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,8 @@ __all__ = ['TestResult', 'TestCase', 'TestSuite',
|
||||||
'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main',
|
'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main',
|
||||||
'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless',
|
'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless',
|
||||||
'expectedFailure', 'TextTestResult', 'installHandler',
|
'expectedFailure', 'TextTestResult', 'installHandler',
|
||||||
'registerResult', 'removeResult', 'removeHandler']
|
'registerResult', 'removeResult', 'removeHandler',
|
||||||
|
'addModuleCleanup']
|
||||||
|
|
||||||
# Expose obsolete functions for backwards compatibility
|
# Expose obsolete functions for backwards compatibility
|
||||||
__all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
|
__all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
|
||||||
|
@ -56,8 +57,8 @@ __all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
|
||||||
__unittest = True
|
__unittest = True
|
||||||
|
|
||||||
from .result import TestResult
|
from .result import TestResult
|
||||||
from .case import (TestCase, FunctionTestCase, SkipTest, skip, skipIf,
|
from .case import (addModuleCleanup, TestCase, FunctionTestCase, SkipTest, skip,
|
||||||
skipUnless, expectedFailure)
|
skipIf, skipUnless, expectedFailure)
|
||||||
from .suite import BaseTestSuite, TestSuite
|
from .suite import BaseTestSuite, TestSuite
|
||||||
from .loader import (TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,
|
from .loader import (TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,
|
||||||
findTestCases)
|
findTestCases)
|
||||||
|
|
|
@ -84,6 +84,30 @@ class _Outcome(object):
|
||||||
def _id(obj):
|
def _id(obj):
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
_module_cleanups = []
|
||||||
|
def addModuleCleanup(function, *args, **kwargs):
|
||||||
|
"""Same as addCleanup, except the cleanup items are called even if
|
||||||
|
setUpModule fails (unlike tearDownModule)."""
|
||||||
|
_module_cleanups.append((function, args, kwargs))
|
||||||
|
|
||||||
|
|
||||||
|
def doModuleCleanups():
|
||||||
|
"""Execute all module cleanup functions. Normally called for you after
|
||||||
|
tearDownModule."""
|
||||||
|
exceptions = []
|
||||||
|
while _module_cleanups:
|
||||||
|
function, args, kwargs = _module_cleanups.pop()
|
||||||
|
try:
|
||||||
|
function(*args, **kwargs)
|
||||||
|
except Exception as exc:
|
||||||
|
exceptions.append(exc)
|
||||||
|
if exceptions:
|
||||||
|
# Swallows all but first exception. If a multi-exception handler
|
||||||
|
# gets written we should use that here instead.
|
||||||
|
raise exceptions[0]
|
||||||
|
|
||||||
|
|
||||||
def skip(reason):
|
def skip(reason):
|
||||||
"""
|
"""
|
||||||
Unconditionally skip a test.
|
Unconditionally skip a test.
|
||||||
|
@ -390,6 +414,8 @@ class TestCase(object):
|
||||||
|
|
||||||
_classSetupFailed = False
|
_classSetupFailed = False
|
||||||
|
|
||||||
|
_class_cleanups = []
|
||||||
|
|
||||||
def __init__(self, methodName='runTest'):
|
def __init__(self, methodName='runTest'):
|
||||||
"""Create an instance of the class that will use the named test
|
"""Create an instance of the class that will use the named test
|
||||||
method when executed. Raises a ValueError if the instance does
|
method when executed. Raises a ValueError if the instance does
|
||||||
|
@ -445,6 +471,12 @@ class TestCase(object):
|
||||||
Cleanup items are called even if setUp fails (unlike tearDown)."""
|
Cleanup items are called even if setUp fails (unlike tearDown)."""
|
||||||
self._cleanups.append((function, args, kwargs))
|
self._cleanups.append((function, args, kwargs))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def addClassCleanup(cls, function, *args, **kwargs):
|
||||||
|
"""Same as addCleanup, except the cleanup items are called even if
|
||||||
|
setUpClass fails (unlike tearDownClass)."""
|
||||||
|
cls._class_cleanups.append((function, args, kwargs))
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"Hook method for setting up the test fixture before exercising it."
|
"Hook method for setting up the test fixture before exercising it."
|
||||||
pass
|
pass
|
||||||
|
@ -651,9 +683,21 @@ class TestCase(object):
|
||||||
function(*args, **kwargs)
|
function(*args, **kwargs)
|
||||||
|
|
||||||
# return this for backwards compatibility
|
# return this for backwards compatibility
|
||||||
# even though we no longer us it internally
|
# even though we no longer use it internally
|
||||||
return outcome.success
|
return outcome.success
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def doClassCleanups(cls):
|
||||||
|
"""Execute all class cleanup functions. Normally called for you after
|
||||||
|
tearDownClass."""
|
||||||
|
cls.tearDown_exceptions = []
|
||||||
|
while cls._class_cleanups:
|
||||||
|
function, args, kwargs = cls._class_cleanups.pop()
|
||||||
|
try:
|
||||||
|
function(*args, **kwargs)
|
||||||
|
except Exception as exc:
|
||||||
|
cls.tearDown_exceptions.append(sys.exc_info())
|
||||||
|
|
||||||
def __call__(self, *args, **kwds):
|
def __call__(self, *args, **kwds):
|
||||||
return self.run(*args, **kwds)
|
return self.run(*args, **kwds)
|
||||||
|
|
||||||
|
|
|
@ -166,10 +166,18 @@ class TestSuite(BaseTestSuite):
|
||||||
raise
|
raise
|
||||||
currentClass._classSetupFailed = True
|
currentClass._classSetupFailed = True
|
||||||
className = util.strclass(currentClass)
|
className = util.strclass(currentClass)
|
||||||
errorName = 'setUpClass (%s)' % className
|
self._createClassOrModuleLevelException(result, e,
|
||||||
self._addClassOrModuleLevelException(result, e, errorName)
|
'setUpClass',
|
||||||
|
className)
|
||||||
finally:
|
finally:
|
||||||
_call_if_exists(result, '_restoreStdout')
|
_call_if_exists(result, '_restoreStdout')
|
||||||
|
if currentClass._classSetupFailed is True:
|
||||||
|
currentClass.doClassCleanups()
|
||||||
|
if len(currentClass.tearDown_exceptions) > 0:
|
||||||
|
for exc in currentClass.tearDown_exceptions:
|
||||||
|
self._createClassOrModuleLevelException(
|
||||||
|
result, exc[1], 'setUpClass', className,
|
||||||
|
info=exc)
|
||||||
|
|
||||||
def _get_previous_module(self, result):
|
def _get_previous_module(self, result):
|
||||||
previousModule = None
|
previousModule = None
|
||||||
|
@ -199,21 +207,37 @@ class TestSuite(BaseTestSuite):
|
||||||
try:
|
try:
|
||||||
setUpModule()
|
setUpModule()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
try:
|
||||||
|
case.doModuleCleanups()
|
||||||
|
except Exception as exc:
|
||||||
|
self._createClassOrModuleLevelException(result, exc,
|
||||||
|
'setUpModule',
|
||||||
|
currentModule)
|
||||||
if isinstance(result, _DebugResult):
|
if isinstance(result, _DebugResult):
|
||||||
raise
|
raise
|
||||||
result._moduleSetUpFailed = True
|
result._moduleSetUpFailed = True
|
||||||
errorName = 'setUpModule (%s)' % currentModule
|
self._createClassOrModuleLevelException(result, e,
|
||||||
self._addClassOrModuleLevelException(result, e, errorName)
|
'setUpModule',
|
||||||
|
currentModule)
|
||||||
finally:
|
finally:
|
||||||
_call_if_exists(result, '_restoreStdout')
|
_call_if_exists(result, '_restoreStdout')
|
||||||
|
|
||||||
def _addClassOrModuleLevelException(self, result, exception, errorName):
|
def _createClassOrModuleLevelException(self, result, exc, method_name,
|
||||||
|
parent, info=None):
|
||||||
|
errorName = f'{method_name} ({parent})'
|
||||||
|
self._addClassOrModuleLevelException(result, exc, errorName, info)
|
||||||
|
|
||||||
|
def _addClassOrModuleLevelException(self, result, exception, errorName,
|
||||||
|
info=None):
|
||||||
error = _ErrorHolder(errorName)
|
error = _ErrorHolder(errorName)
|
||||||
addSkip = getattr(result, 'addSkip', None)
|
addSkip = getattr(result, 'addSkip', None)
|
||||||
if addSkip is not None and isinstance(exception, case.SkipTest):
|
if addSkip is not None and isinstance(exception, case.SkipTest):
|
||||||
addSkip(error, str(exception))
|
addSkip(error, str(exception))
|
||||||
else:
|
else:
|
||||||
result.addError(error, sys.exc_info())
|
if not info:
|
||||||
|
result.addError(error, sys.exc_info())
|
||||||
|
else:
|
||||||
|
result.addError(error, info)
|
||||||
|
|
||||||
def _handleModuleTearDown(self, result):
|
def _handleModuleTearDown(self, result):
|
||||||
previousModule = self._get_previous_module(result)
|
previousModule = self._get_previous_module(result)
|
||||||
|
@ -235,10 +259,17 @@ class TestSuite(BaseTestSuite):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if isinstance(result, _DebugResult):
|
if isinstance(result, _DebugResult):
|
||||||
raise
|
raise
|
||||||
errorName = 'tearDownModule (%s)' % previousModule
|
self._createClassOrModuleLevelException(result, e,
|
||||||
self._addClassOrModuleLevelException(result, e, errorName)
|
'tearDownModule',
|
||||||
|
previousModule)
|
||||||
finally:
|
finally:
|
||||||
_call_if_exists(result, '_restoreStdout')
|
_call_if_exists(result, '_restoreStdout')
|
||||||
|
try:
|
||||||
|
case.doModuleCleanups()
|
||||||
|
except Exception as e:
|
||||||
|
self._createClassOrModuleLevelException(result, e,
|
||||||
|
'tearDownModule',
|
||||||
|
previousModule)
|
||||||
|
|
||||||
def _tearDownPreviousClass(self, test, result):
|
def _tearDownPreviousClass(self, test, result):
|
||||||
previousClass = getattr(result, '_previousTestClass', None)
|
previousClass = getattr(result, '_previousTestClass', None)
|
||||||
|
@ -261,10 +292,19 @@ class TestSuite(BaseTestSuite):
|
||||||
if isinstance(result, _DebugResult):
|
if isinstance(result, _DebugResult):
|
||||||
raise
|
raise
|
||||||
className = util.strclass(previousClass)
|
className = util.strclass(previousClass)
|
||||||
errorName = 'tearDownClass (%s)' % className
|
self._createClassOrModuleLevelException(result, e,
|
||||||
self._addClassOrModuleLevelException(result, e, errorName)
|
'tearDownClass',
|
||||||
|
className)
|
||||||
finally:
|
finally:
|
||||||
_call_if_exists(result, '_restoreStdout')
|
_call_if_exists(result, '_restoreStdout')
|
||||||
|
previousClass.doClassCleanups()
|
||||||
|
if len(previousClass.tearDown_exceptions) > 0:
|
||||||
|
for exc in previousClass.tearDown_exceptions:
|
||||||
|
className = util.strclass(previousClass)
|
||||||
|
self._createClassOrModuleLevelException(result, exc[1],
|
||||||
|
'tearDownClass',
|
||||||
|
className,
|
||||||
|
info=exc)
|
||||||
|
|
||||||
|
|
||||||
class _ErrorHolder(object):
|
class _ErrorHolder(object):
|
||||||
|
|
|
@ -11,8 +11,41 @@ from unittest.test.support import (LoggingResult,
|
||||||
ResultWithNoStartTestRunStopTestRun)
|
ResultWithNoStartTestRunStopTestRun)
|
||||||
|
|
||||||
|
|
||||||
class TestCleanUp(unittest.TestCase):
|
def resultFactory(*_):
|
||||||
|
return unittest.TestResult()
|
||||||
|
|
||||||
|
|
||||||
|
def getRunner():
|
||||||
|
return unittest.TextTestRunner(resultclass=resultFactory,
|
||||||
|
stream=io.StringIO())
|
||||||
|
|
||||||
|
|
||||||
|
def runTests(*cases):
|
||||||
|
suite = unittest.TestSuite()
|
||||||
|
for case in cases:
|
||||||
|
tests = unittest.defaultTestLoader.loadTestsFromTestCase(case)
|
||||||
|
suite.addTests(tests)
|
||||||
|
|
||||||
|
runner = getRunner()
|
||||||
|
|
||||||
|
# creating a nested suite exposes some potential bugs
|
||||||
|
realSuite = unittest.TestSuite()
|
||||||
|
realSuite.addTest(suite)
|
||||||
|
# adding empty suites to the end exposes potential bugs
|
||||||
|
suite.addTest(unittest.TestSuite())
|
||||||
|
realSuite.addTest(unittest.TestSuite())
|
||||||
|
return runner.run(realSuite)
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup(ordering, blowUp=False):
|
||||||
|
if not blowUp:
|
||||||
|
ordering.append('cleanup_good')
|
||||||
|
else:
|
||||||
|
ordering.append('cleanup_exc')
|
||||||
|
raise Exception('CleanUpExc')
|
||||||
|
|
||||||
|
|
||||||
|
class TestCleanUp(unittest.TestCase):
|
||||||
def testCleanUp(self):
|
def testCleanUp(self):
|
||||||
class TestableTest(unittest.TestCase):
|
class TestableTest(unittest.TestCase):
|
||||||
def testNothing(self):
|
def testNothing(self):
|
||||||
|
@ -47,10 +80,10 @@ class TestCleanUp(unittest.TestCase):
|
||||||
test = TestableTest('testNothing')
|
test = TestableTest('testNothing')
|
||||||
outcome = test._outcome = _Outcome()
|
outcome = test._outcome = _Outcome()
|
||||||
|
|
||||||
exc1 = Exception('foo')
|
CleanUpExc = Exception('foo')
|
||||||
exc2 = Exception('bar')
|
exc2 = Exception('bar')
|
||||||
def cleanup1():
|
def cleanup1():
|
||||||
raise exc1
|
raise CleanUpExc
|
||||||
|
|
||||||
def cleanup2():
|
def cleanup2():
|
||||||
raise exc2
|
raise exc2
|
||||||
|
@ -63,7 +96,7 @@ class TestCleanUp(unittest.TestCase):
|
||||||
|
|
||||||
((_, (Type1, instance1, _)),
|
((_, (Type1, instance1, _)),
|
||||||
(_, (Type2, instance2, _))) = reversed(outcome.errors)
|
(_, (Type2, instance2, _))) = reversed(outcome.errors)
|
||||||
self.assertEqual((Type1, instance1), (Exception, exc1))
|
self.assertEqual((Type1, instance1), (Exception, CleanUpExc))
|
||||||
self.assertEqual((Type2, instance2), (Exception, exc2))
|
self.assertEqual((Type2, instance2), (Exception, exc2))
|
||||||
|
|
||||||
def testCleanupInRun(self):
|
def testCleanupInRun(self):
|
||||||
|
@ -135,6 +168,575 @@ class TestCleanUp(unittest.TestCase):
|
||||||
self.assertEqual(ordering, ['setUp', 'test', 'tearDown', 'cleanup1', 'cleanup2'])
|
self.assertEqual(ordering, ['setUp', 'test', 'tearDown', 'cleanup1', 'cleanup2'])
|
||||||
|
|
||||||
|
|
||||||
|
class TestClassCleanup(unittest.TestCase):
|
||||||
|
def test_addClassCleanUp(self):
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
def testNothing(self):
|
||||||
|
pass
|
||||||
|
test = TestableTest('testNothing')
|
||||||
|
self.assertEqual(test._class_cleanups, [])
|
||||||
|
class_cleanups = []
|
||||||
|
|
||||||
|
def class_cleanup1(*args, **kwargs):
|
||||||
|
class_cleanups.append((3, args, kwargs))
|
||||||
|
|
||||||
|
def class_cleanup2(*args, **kwargs):
|
||||||
|
class_cleanups.append((4, args, kwargs))
|
||||||
|
|
||||||
|
TestableTest.addClassCleanup(class_cleanup1, 1, 2, 3,
|
||||||
|
four='hello', five='goodbye')
|
||||||
|
TestableTest.addClassCleanup(class_cleanup2)
|
||||||
|
|
||||||
|
self.assertEqual(test._class_cleanups,
|
||||||
|
[(class_cleanup1, (1, 2, 3),
|
||||||
|
dict(four='hello', five='goodbye')),
|
||||||
|
(class_cleanup2, (), {})])
|
||||||
|
|
||||||
|
TestableTest.doClassCleanups()
|
||||||
|
self.assertEqual(class_cleanups, [(4, (), {}), (3, (1, 2, 3),
|
||||||
|
dict(four='hello', five='goodbye'))])
|
||||||
|
|
||||||
|
def test_run_class_cleanUp(self):
|
||||||
|
ordering = []
|
||||||
|
blowUp = True
|
||||||
|
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
ordering.append('setUpClass')
|
||||||
|
cls.addClassCleanup(cleanup, ordering)
|
||||||
|
if blowUp:
|
||||||
|
raise Exception()
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test')
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
ordering.append('tearDownClass')
|
||||||
|
|
||||||
|
runTests(TestableTest)
|
||||||
|
self.assertEqual(ordering, ['setUpClass', 'cleanup_good'])
|
||||||
|
|
||||||
|
ordering = []
|
||||||
|
blowUp = False
|
||||||
|
runTests(TestableTest)
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpClass', 'test', 'tearDownClass', 'cleanup_good'])
|
||||||
|
|
||||||
|
def test_debug_executes_classCleanUp(self):
|
||||||
|
ordering = []
|
||||||
|
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
ordering.append('setUpClass')
|
||||||
|
cls.addClassCleanup(cleanup, ordering)
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test')
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
ordering.append('tearDownClass')
|
||||||
|
|
||||||
|
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||||
|
suite.debug()
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpClass', 'test', 'tearDownClass', 'cleanup_good'])
|
||||||
|
|
||||||
|
def test_doClassCleanups_with_errors_addClassCleanUp(self):
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
def testNothing(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def cleanup1():
|
||||||
|
raise Exception('cleanup1')
|
||||||
|
|
||||||
|
def cleanup2():
|
||||||
|
raise Exception('cleanup2')
|
||||||
|
|
||||||
|
TestableTest.addClassCleanup(cleanup1)
|
||||||
|
TestableTest.addClassCleanup(cleanup2)
|
||||||
|
with self.assertRaises(Exception) as e:
|
||||||
|
TestableTest.doClassCleanups()
|
||||||
|
self.assertEquals(e, 'cleanup1')
|
||||||
|
|
||||||
|
def test_with_errors_addCleanUp(self):
|
||||||
|
ordering = []
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
ordering.append('setUpClass')
|
||||||
|
cls.addClassCleanup(cleanup, ordering)
|
||||||
|
def setUp(self):
|
||||||
|
ordering.append('setUp')
|
||||||
|
self.addCleanup(cleanup, ordering, blowUp=True)
|
||||||
|
def testNothing(self):
|
||||||
|
pass
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
ordering.append('tearDownClass')
|
||||||
|
|
||||||
|
result = runTests(TestableTest)
|
||||||
|
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||||
|
'Exception: CleanUpExc')
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpClass', 'setUp', 'cleanup_exc',
|
||||||
|
'tearDownClass', 'cleanup_good'])
|
||||||
|
|
||||||
|
def test_run_with_errors_addClassCleanUp(self):
|
||||||
|
ordering = []
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
ordering.append('setUpClass')
|
||||||
|
cls.addClassCleanup(cleanup, ordering, blowUp=True)
|
||||||
|
def setUp(self):
|
||||||
|
ordering.append('setUp')
|
||||||
|
self.addCleanup(cleanup, ordering)
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test')
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
ordering.append('tearDownClass')
|
||||||
|
|
||||||
|
result = runTests(TestableTest)
|
||||||
|
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||||
|
'Exception: CleanUpExc')
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpClass', 'setUp', 'test', 'cleanup_good',
|
||||||
|
'tearDownClass', 'cleanup_exc'])
|
||||||
|
|
||||||
|
def test_with_errors_in_addClassCleanup_and_setUps(self):
|
||||||
|
ordering = []
|
||||||
|
class_blow_up = False
|
||||||
|
method_blow_up = False
|
||||||
|
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
ordering.append('setUpClass')
|
||||||
|
cls.addClassCleanup(cleanup, ordering, blowUp=True)
|
||||||
|
if class_blow_up:
|
||||||
|
raise Exception('ClassExc')
|
||||||
|
def setUp(self):
|
||||||
|
ordering.append('setUp')
|
||||||
|
if method_blow_up:
|
||||||
|
raise Exception('MethodExc')
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test')
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
ordering.append('tearDownClass')
|
||||||
|
|
||||||
|
result = runTests(TestableTest)
|
||||||
|
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||||
|
'Exception: CleanUpExc')
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpClass', 'setUp', 'test',
|
||||||
|
'tearDownClass', 'cleanup_exc'])
|
||||||
|
ordering = []
|
||||||
|
class_blow_up = True
|
||||||
|
method_blow_up = False
|
||||||
|
result = runTests(TestableTest)
|
||||||
|
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||||
|
'Exception: ClassExc')
|
||||||
|
self.assertEqual(result.errors[1][1].splitlines()[-1],
|
||||||
|
'Exception: CleanUpExc')
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpClass', 'cleanup_exc'])
|
||||||
|
|
||||||
|
ordering = []
|
||||||
|
class_blow_up = False
|
||||||
|
method_blow_up = True
|
||||||
|
result = runTests(TestableTest)
|
||||||
|
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||||
|
'Exception: MethodExc')
|
||||||
|
self.assertEqual(result.errors[1][1].splitlines()[-1],
|
||||||
|
'Exception: CleanUpExc')
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpClass', 'setUp', 'tearDownClass',
|
||||||
|
'cleanup_exc'])
|
||||||
|
|
||||||
|
|
||||||
|
class TestModuleCleanUp(unittest.TestCase):
|
||||||
|
def test_add_and_do_ModuleCleanup(self):
|
||||||
|
module_cleanups = []
|
||||||
|
|
||||||
|
def module_cleanup1(*args, **kwargs):
|
||||||
|
module_cleanups.append((3, args, kwargs))
|
||||||
|
|
||||||
|
def module_cleanup2(*args, **kwargs):
|
||||||
|
module_cleanups.append((4, args, kwargs))
|
||||||
|
|
||||||
|
class Module(object):
|
||||||
|
unittest.addModuleCleanup(module_cleanup1, 1, 2, 3,
|
||||||
|
four='hello', five='goodbye')
|
||||||
|
unittest.addModuleCleanup(module_cleanup2)
|
||||||
|
|
||||||
|
self.assertEqual(unittest.case._module_cleanups,
|
||||||
|
[(module_cleanup1, (1, 2, 3),
|
||||||
|
dict(four='hello', five='goodbye')),
|
||||||
|
(module_cleanup2, (), {})])
|
||||||
|
|
||||||
|
unittest.case.doModuleCleanups()
|
||||||
|
self.assertEqual(module_cleanups, [(4, (), {}), (3, (1, 2, 3),
|
||||||
|
dict(four='hello', five='goodbye'))])
|
||||||
|
self.assertEqual(unittest.case._module_cleanups, [])
|
||||||
|
|
||||||
|
def test_doModuleCleanup_with_errors_in_addModuleCleanup(self):
|
||||||
|
module_cleanups = []
|
||||||
|
|
||||||
|
def module_cleanup_good(*args, **kwargs):
|
||||||
|
module_cleanups.append((3, args, kwargs))
|
||||||
|
|
||||||
|
def module_cleanup_bad(*args, **kwargs):
|
||||||
|
raise Exception('CleanUpExc')
|
||||||
|
|
||||||
|
class Module(object):
|
||||||
|
unittest.addModuleCleanup(module_cleanup_good, 1, 2, 3,
|
||||||
|
four='hello', five='goodbye')
|
||||||
|
unittest.addModuleCleanup(module_cleanup_bad)
|
||||||
|
self.assertEqual(unittest.case._module_cleanups,
|
||||||
|
[(module_cleanup_good, (1, 2, 3),
|
||||||
|
dict(four='hello', five='goodbye')),
|
||||||
|
(module_cleanup_bad, (), {})])
|
||||||
|
with self.assertRaises(Exception) as e:
|
||||||
|
unittest.case.doModuleCleanups()
|
||||||
|
self.assertEqual(str(e.exception), 'CleanUpExc')
|
||||||
|
self.assertEqual(unittest.case._module_cleanups, [])
|
||||||
|
|
||||||
|
def test_run_module_cleanUp(self):
|
||||||
|
blowUp = True
|
||||||
|
ordering = []
|
||||||
|
class Module(object):
|
||||||
|
@staticmethod
|
||||||
|
def setUpModule():
|
||||||
|
ordering.append('setUpModule')
|
||||||
|
unittest.addModuleCleanup(cleanup, ordering)
|
||||||
|
if blowUp:
|
||||||
|
raise Exception('setUpModule Exc')
|
||||||
|
@staticmethod
|
||||||
|
def tearDownModule():
|
||||||
|
ordering.append('tearDownModule')
|
||||||
|
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
ordering.append('setUpClass')
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test')
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
ordering.append('tearDownClass')
|
||||||
|
|
||||||
|
TestableTest.__module__ = 'Module'
|
||||||
|
sys.modules['Module'] = Module
|
||||||
|
result = runTests(TestableTest)
|
||||||
|
self.assertEqual(ordering, ['setUpModule', 'cleanup_good'])
|
||||||
|
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||||
|
'Exception: setUpModule Exc')
|
||||||
|
|
||||||
|
ordering = []
|
||||||
|
blowUp = False
|
||||||
|
runTests(TestableTest)
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpModule', 'setUpClass', 'test', 'tearDownClass',
|
||||||
|
'tearDownModule', 'cleanup_good'])
|
||||||
|
self.assertEqual(unittest.case._module_cleanups, [])
|
||||||
|
|
||||||
|
def test_run_multiple_module_cleanUp(self):
|
||||||
|
blowUp = True
|
||||||
|
blowUp2 = False
|
||||||
|
ordering = []
|
||||||
|
class Module1(object):
|
||||||
|
@staticmethod
|
||||||
|
def setUpModule():
|
||||||
|
ordering.append('setUpModule')
|
||||||
|
unittest.addModuleCleanup(cleanup, ordering)
|
||||||
|
if blowUp:
|
||||||
|
raise Exception()
|
||||||
|
@staticmethod
|
||||||
|
def tearDownModule():
|
||||||
|
ordering.append('tearDownModule')
|
||||||
|
|
||||||
|
class Module2(object):
|
||||||
|
@staticmethod
|
||||||
|
def setUpModule():
|
||||||
|
ordering.append('setUpModule2')
|
||||||
|
unittest.addModuleCleanup(cleanup, ordering)
|
||||||
|
if blowUp2:
|
||||||
|
raise Exception()
|
||||||
|
@staticmethod
|
||||||
|
def tearDownModule():
|
||||||
|
ordering.append('tearDownModule2')
|
||||||
|
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
ordering.append('setUpClass')
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test')
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
ordering.append('tearDownClass')
|
||||||
|
|
||||||
|
class TestableTest2(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
ordering.append('setUpClass2')
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test2')
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
ordering.append('tearDownClass2')
|
||||||
|
|
||||||
|
TestableTest.__module__ = 'Module1'
|
||||||
|
sys.modules['Module1'] = Module1
|
||||||
|
TestableTest2.__module__ = 'Module2'
|
||||||
|
sys.modules['Module2'] = Module2
|
||||||
|
runTests(TestableTest, TestableTest2)
|
||||||
|
self.assertEqual(ordering, ['setUpModule', 'cleanup_good',
|
||||||
|
'setUpModule2', 'setUpClass2', 'test2',
|
||||||
|
'tearDownClass2', 'tearDownModule2',
|
||||||
|
'cleanup_good'])
|
||||||
|
ordering = []
|
||||||
|
blowUp = False
|
||||||
|
blowUp2 = True
|
||||||
|
runTests(TestableTest, TestableTest2)
|
||||||
|
self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
|
||||||
|
'tearDownClass', 'tearDownModule',
|
||||||
|
'cleanup_good', 'setUpModule2',
|
||||||
|
'cleanup_good'])
|
||||||
|
|
||||||
|
ordering = []
|
||||||
|
blowUp = False
|
||||||
|
blowUp2 = False
|
||||||
|
runTests(TestableTest, TestableTest2)
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpModule', 'setUpClass', 'test', 'tearDownClass',
|
||||||
|
'tearDownModule', 'cleanup_good', 'setUpModule2',
|
||||||
|
'setUpClass2', 'test2', 'tearDownClass2',
|
||||||
|
'tearDownModule2', 'cleanup_good'])
|
||||||
|
self.assertEqual(unittest.case._module_cleanups, [])
|
||||||
|
|
||||||
|
def test_debug_module_executes_cleanUp(self):
|
||||||
|
ordering = []
|
||||||
|
class Module(object):
|
||||||
|
@staticmethod
|
||||||
|
def setUpModule():
|
||||||
|
ordering.append('setUpModule')
|
||||||
|
unittest.addModuleCleanup(cleanup, ordering)
|
||||||
|
@staticmethod
|
||||||
|
def tearDownModule():
|
||||||
|
ordering.append('tearDownModule')
|
||||||
|
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
ordering.append('setUpClass')
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test')
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
ordering.append('tearDownClass')
|
||||||
|
|
||||||
|
TestableTest.__module__ = 'Module'
|
||||||
|
sys.modules['Module'] = Module
|
||||||
|
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||||
|
suite.debug()
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpModule', 'setUpClass', 'test', 'tearDownClass',
|
||||||
|
'tearDownModule', 'cleanup_good'])
|
||||||
|
self.assertEqual(unittest.case._module_cleanups, [])
|
||||||
|
|
||||||
|
def test_with_errors_in_addClassCleanup(self):
|
||||||
|
ordering = []
|
||||||
|
|
||||||
|
class Module(object):
|
||||||
|
@staticmethod
|
||||||
|
def setUpModule():
|
||||||
|
ordering.append('setUpModule')
|
||||||
|
unittest.addModuleCleanup(cleanup, ordering)
|
||||||
|
@staticmethod
|
||||||
|
def tearDownModule():
|
||||||
|
ordering.append('tearDownModule')
|
||||||
|
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
ordering.append('setUpClass')
|
||||||
|
cls.addClassCleanup(cleanup, ordering, blowUp=True)
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test')
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
ordering.append('tearDownClass')
|
||||||
|
|
||||||
|
TestableTest.__module__ = 'Module'
|
||||||
|
sys.modules['Module'] = Module
|
||||||
|
|
||||||
|
result = runTests(TestableTest)
|
||||||
|
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||||
|
'Exception: CleanUpExc')
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpModule', 'setUpClass', 'test', 'tearDownClass',
|
||||||
|
'cleanup_exc', 'tearDownModule', 'cleanup_good'])
|
||||||
|
|
||||||
|
def test_with_errors_in_addCleanup(self):
|
||||||
|
ordering = []
|
||||||
|
class Module(object):
|
||||||
|
@staticmethod
|
||||||
|
def setUpModule():
|
||||||
|
ordering.append('setUpModule')
|
||||||
|
unittest.addModuleCleanup(cleanup, ordering)
|
||||||
|
@staticmethod
|
||||||
|
def tearDownModule():
|
||||||
|
ordering.append('tearDownModule')
|
||||||
|
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
ordering.append('setUp')
|
||||||
|
self.addCleanup(cleanup, ordering, blowUp=True)
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test')
|
||||||
|
def tearDown(self):
|
||||||
|
ordering.append('tearDown')
|
||||||
|
|
||||||
|
TestableTest.__module__ = 'Module'
|
||||||
|
sys.modules['Module'] = Module
|
||||||
|
|
||||||
|
result = runTests(TestableTest)
|
||||||
|
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||||
|
'Exception: CleanUpExc')
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpModule', 'setUp', 'test', 'tearDown',
|
||||||
|
'cleanup_exc', 'tearDownModule', 'cleanup_good'])
|
||||||
|
|
||||||
|
def test_with_errors_in_addModuleCleanup_and_setUps(self):
|
||||||
|
ordering = []
|
||||||
|
module_blow_up = False
|
||||||
|
class_blow_up = False
|
||||||
|
method_blow_up = False
|
||||||
|
class Module(object):
|
||||||
|
@staticmethod
|
||||||
|
def setUpModule():
|
||||||
|
ordering.append('setUpModule')
|
||||||
|
unittest.addModuleCleanup(cleanup, ordering, blowUp=True)
|
||||||
|
if module_blow_up:
|
||||||
|
raise Exception('ModuleExc')
|
||||||
|
@staticmethod
|
||||||
|
def tearDownModule():
|
||||||
|
ordering.append('tearDownModule')
|
||||||
|
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
ordering.append('setUpClass')
|
||||||
|
if class_blow_up:
|
||||||
|
raise Exception('ClassExc')
|
||||||
|
def setUp(self):
|
||||||
|
ordering.append('setUp')
|
||||||
|
if method_blow_up:
|
||||||
|
raise Exception('MethodExc')
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test')
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
ordering.append('tearDownClass')
|
||||||
|
|
||||||
|
TestableTest.__module__ = 'Module'
|
||||||
|
sys.modules['Module'] = Module
|
||||||
|
|
||||||
|
result = runTests(TestableTest)
|
||||||
|
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||||
|
'Exception: CleanUpExc')
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpModule', 'setUpClass', 'setUp', 'test',
|
||||||
|
'tearDownClass', 'tearDownModule',
|
||||||
|
'cleanup_exc'])
|
||||||
|
|
||||||
|
ordering = []
|
||||||
|
module_blow_up = True
|
||||||
|
class_blow_up = False
|
||||||
|
method_blow_up = False
|
||||||
|
result = runTests(TestableTest)
|
||||||
|
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||||
|
'Exception: CleanUpExc')
|
||||||
|
self.assertEqual(result.errors[1][1].splitlines()[-1],
|
||||||
|
'Exception: ModuleExc')
|
||||||
|
self.assertEqual(ordering, ['setUpModule', 'cleanup_exc'])
|
||||||
|
|
||||||
|
ordering = []
|
||||||
|
module_blow_up = False
|
||||||
|
class_blow_up = True
|
||||||
|
method_blow_up = False
|
||||||
|
result = runTests(TestableTest)
|
||||||
|
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||||
|
'Exception: ClassExc')
|
||||||
|
self.assertEqual(result.errors[1][1].splitlines()[-1],
|
||||||
|
'Exception: CleanUpExc')
|
||||||
|
self.assertEqual(ordering, ['setUpModule', 'setUpClass',
|
||||||
|
'tearDownModule', 'cleanup_exc'])
|
||||||
|
|
||||||
|
ordering = []
|
||||||
|
module_blow_up = False
|
||||||
|
class_blow_up = False
|
||||||
|
method_blow_up = True
|
||||||
|
result = runTests(TestableTest)
|
||||||
|
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||||
|
'Exception: MethodExc')
|
||||||
|
self.assertEqual(result.errors[1][1].splitlines()[-1],
|
||||||
|
'Exception: CleanUpExc')
|
||||||
|
self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'setUp',
|
||||||
|
'tearDownClass', 'tearDownModule',
|
||||||
|
'cleanup_exc'])
|
||||||
|
|
||||||
|
def test_module_cleanUp_with_multiple_classes(self):
|
||||||
|
ordering =[]
|
||||||
|
def cleanup1():
|
||||||
|
ordering.append('cleanup1')
|
||||||
|
|
||||||
|
def cleanup2():
|
||||||
|
ordering.append('cleanup2')
|
||||||
|
|
||||||
|
def cleanup3():
|
||||||
|
ordering.append('cleanup3')
|
||||||
|
|
||||||
|
class Module(object):
|
||||||
|
@staticmethod
|
||||||
|
def setUpModule():
|
||||||
|
ordering.append('setUpModule')
|
||||||
|
unittest.addModuleCleanup(cleanup1)
|
||||||
|
@staticmethod
|
||||||
|
def tearDownModule():
|
||||||
|
ordering.append('tearDownModule')
|
||||||
|
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
ordering.append('setUp')
|
||||||
|
self.addCleanup(cleanup2)
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test')
|
||||||
|
def tearDown(self):
|
||||||
|
ordering.append('tearDown')
|
||||||
|
|
||||||
|
class OtherTestableTest(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
ordering.append('setUp2')
|
||||||
|
self.addCleanup(cleanup3)
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test2')
|
||||||
|
def tearDown(self):
|
||||||
|
ordering.append('tearDown2')
|
||||||
|
|
||||||
|
TestableTest.__module__ = 'Module'
|
||||||
|
OtherTestableTest.__module__ = 'Module'
|
||||||
|
sys.modules['Module'] = Module
|
||||||
|
runTests(TestableTest, OtherTestableTest)
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpModule', 'setUp', 'test', 'tearDown',
|
||||||
|
'cleanup2', 'setUp2', 'test2', 'tearDown2',
|
||||||
|
'cleanup3', 'tearDownModule', 'cleanup1'])
|
||||||
|
|
||||||
|
|
||||||
class Test_TextTestRunner(unittest.TestCase):
|
class Test_TextTestRunner(unittest.TestCase):
|
||||||
"""Tests for TextTestRunner."""
|
"""Tests for TextTestRunner."""
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Add :func:`~unittest.addModuleCleanup()` and
|
||||||
|
:meth:`~unittest.TestCase.addClassCleanup()` to unittest to support
|
||||||
|
cleanups for :func:`~unittest.setUpModule()` and
|
||||||
|
:meth:`~unittest.TestCase.setUpClass()`. Patch by Lisa Roach.
|
Loading…
Reference in New Issue