mirror of
https://github.com/python/cpython.git
synced 2025-07-24 19:54:21 +00:00
bpo-43913: Fix bugs in cleaning up classes and modules in unittest. (GH-28006)
* Functions registered with addModuleCleanup() were not called unless the user defines tearDownModule() in their test module. * Functions registered with addClassCleanup() were not called if tearDownClass is set to None. * Buffering in TestResult did not work with functions registered with addClassCleanup() and addModuleCleanup(). * Errors in functions registered with addClassCleanup() and addModuleCleanup() were not handled correctly in buffered and debug modes. * Errors in setUpModule() and functions registered with addModuleCleanup() were reported in wrong order. * And several lesser bugs.
This commit is contained in:
parent
7e246a3a7b
commit
08d9e597c8
4 changed files with 719 additions and 70 deletions
|
@ -149,6 +149,7 @@ class TestSuite(BaseTestSuite):
|
||||||
if getattr(currentClass, "__unittest_skip__", False):
|
if getattr(currentClass, "__unittest_skip__", False):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
failed = False
|
||||||
try:
|
try:
|
||||||
currentClass._classSetupFailed = False
|
currentClass._classSetupFailed = False
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
@ -157,27 +158,32 @@ class TestSuite(BaseTestSuite):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
setUpClass = getattr(currentClass, 'setUpClass', None)
|
setUpClass = getattr(currentClass, 'setUpClass', None)
|
||||||
|
doClassCleanups = getattr(currentClass, 'doClassCleanups', None)
|
||||||
if setUpClass is not None:
|
if setUpClass is not None:
|
||||||
_call_if_exists(result, '_setupStdout')
|
_call_if_exists(result, '_setupStdout')
|
||||||
try:
|
try:
|
||||||
setUpClass()
|
try:
|
||||||
except Exception as e:
|
setUpClass()
|
||||||
if isinstance(result, _DebugResult):
|
except Exception as e:
|
||||||
raise
|
if isinstance(result, _DebugResult):
|
||||||
currentClass._classSetupFailed = True
|
raise
|
||||||
className = util.strclass(currentClass)
|
failed = True
|
||||||
self._createClassOrModuleLevelException(result, e,
|
try:
|
||||||
'setUpClass',
|
currentClass._classSetupFailed = True
|
||||||
className)
|
except TypeError:
|
||||||
|
pass
|
||||||
|
className = util.strclass(currentClass)
|
||||||
|
self._createClassOrModuleLevelException(result, e,
|
||||||
|
'setUpClass',
|
||||||
|
className)
|
||||||
|
if failed and doClassCleanups is not None:
|
||||||
|
doClassCleanups()
|
||||||
|
for exc_info in currentClass.tearDown_exceptions:
|
||||||
|
self._createClassOrModuleLevelException(
|
||||||
|
result, exc_info[1], 'setUpClass', className,
|
||||||
|
info=exc_info)
|
||||||
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
|
||||||
|
@ -205,20 +211,22 @@ class TestSuite(BaseTestSuite):
|
||||||
if setUpModule is not None:
|
if setUpModule is not None:
|
||||||
_call_if_exists(result, '_setupStdout')
|
_call_if_exists(result, '_setupStdout')
|
||||||
try:
|
try:
|
||||||
setUpModule()
|
|
||||||
except Exception as e:
|
|
||||||
try:
|
try:
|
||||||
case.doModuleCleanups()
|
setUpModule()
|
||||||
except Exception as exc:
|
except Exception as e:
|
||||||
self._createClassOrModuleLevelException(result, exc,
|
if isinstance(result, _DebugResult):
|
||||||
|
raise
|
||||||
|
result._moduleSetUpFailed = True
|
||||||
|
self._createClassOrModuleLevelException(result, e,
|
||||||
'setUpModule',
|
'setUpModule',
|
||||||
currentModule)
|
currentModule)
|
||||||
if isinstance(result, _DebugResult):
|
if result._moduleSetUpFailed:
|
||||||
raise
|
try:
|
||||||
result._moduleSetUpFailed = True
|
case.doModuleCleanups()
|
||||||
self._createClassOrModuleLevelException(result, e,
|
except Exception as e:
|
||||||
'setUpModule',
|
self._createClassOrModuleLevelException(result, e,
|
||||||
currentModule)
|
'setUpModule',
|
||||||
|
currentModule)
|
||||||
finally:
|
finally:
|
||||||
_call_if_exists(result, '_restoreStdout')
|
_call_if_exists(result, '_restoreStdout')
|
||||||
|
|
||||||
|
@ -251,30 +259,33 @@ class TestSuite(BaseTestSuite):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return
|
return
|
||||||
|
|
||||||
tearDownModule = getattr(module, 'tearDownModule', None)
|
_call_if_exists(result, '_setupStdout')
|
||||||
if tearDownModule is not None:
|
try:
|
||||||
_call_if_exists(result, '_setupStdout')
|
tearDownModule = getattr(module, 'tearDownModule', None)
|
||||||
|
if tearDownModule is not None:
|
||||||
|
try:
|
||||||
|
tearDownModule()
|
||||||
|
except Exception as e:
|
||||||
|
if isinstance(result, _DebugResult):
|
||||||
|
raise
|
||||||
|
self._createClassOrModuleLevelException(result, e,
|
||||||
|
'tearDownModule',
|
||||||
|
previousModule)
|
||||||
try:
|
try:
|
||||||
tearDownModule()
|
case.doModuleCleanups()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if isinstance(result, _DebugResult):
|
if isinstance(result, _DebugResult):
|
||||||
raise
|
raise
|
||||||
self._createClassOrModuleLevelException(result, e,
|
self._createClassOrModuleLevelException(result, e,
|
||||||
'tearDownModule',
|
'tearDownModule',
|
||||||
previousModule)
|
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)
|
||||||
currentClass = test.__class__
|
currentClass = test.__class__
|
||||||
if currentClass == previousClass:
|
if currentClass == previousClass or previousClass is None:
|
||||||
return
|
return
|
||||||
if getattr(previousClass, '_classSetupFailed', False):
|
if getattr(previousClass, '_classSetupFailed', False):
|
||||||
return
|
return
|
||||||
|
@ -284,27 +295,34 @@ class TestSuite(BaseTestSuite):
|
||||||
return
|
return
|
||||||
|
|
||||||
tearDownClass = getattr(previousClass, 'tearDownClass', None)
|
tearDownClass = getattr(previousClass, 'tearDownClass', None)
|
||||||
if tearDownClass is not None:
|
doClassCleanups = getattr(previousClass, 'doClassCleanups', None)
|
||||||
_call_if_exists(result, '_setupStdout')
|
if tearDownClass is None and doClassCleanups is None:
|
||||||
try:
|
return
|
||||||
tearDownClass()
|
|
||||||
except Exception as e:
|
_call_if_exists(result, '_setupStdout')
|
||||||
if isinstance(result, _DebugResult):
|
try:
|
||||||
raise
|
if tearDownClass is not None:
|
||||||
className = util.strclass(previousClass)
|
try:
|
||||||
self._createClassOrModuleLevelException(result, e,
|
tearDownClass()
|
||||||
'tearDownClass',
|
except Exception as e:
|
||||||
className)
|
if isinstance(result, _DebugResult):
|
||||||
finally:
|
raise
|
||||||
_call_if_exists(result, '_restoreStdout')
|
className = util.strclass(previousClass)
|
||||||
previousClass.doClassCleanups()
|
self._createClassOrModuleLevelException(result, e,
|
||||||
if len(previousClass.tearDown_exceptions) > 0:
|
'tearDownClass',
|
||||||
for exc in previousClass.tearDown_exceptions:
|
className)
|
||||||
className = util.strclass(previousClass)
|
if doClassCleanups is not None:
|
||||||
self._createClassOrModuleLevelException(result, exc[1],
|
doClassCleanups()
|
||||||
'tearDownClass',
|
for exc_info in previousClass.tearDown_exceptions:
|
||||||
className,
|
if isinstance(result, _DebugResult):
|
||||||
info=exc)
|
raise exc_info[1]
|
||||||
|
className = util.strclass(previousClass)
|
||||||
|
self._createClassOrModuleLevelException(result, exc_info[1],
|
||||||
|
'tearDownClass',
|
||||||
|
className,
|
||||||
|
info=exc_info)
|
||||||
|
finally:
|
||||||
|
_call_if_exists(result, '_restoreStdout')
|
||||||
|
|
||||||
|
|
||||||
class _ErrorHolder(object):
|
class _ErrorHolder(object):
|
||||||
|
|
|
@ -2,10 +2,11 @@ import io
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
from test.support import warnings_helper
|
from test.support import warnings_helper, captured_stdout, captured_stderr
|
||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
import unittest
|
import unittest
|
||||||
|
from unittest.util import strclass
|
||||||
|
|
||||||
|
|
||||||
class MockTraceback(object):
|
class MockTraceback(object):
|
||||||
|
@ -22,6 +23,16 @@ def restore_traceback():
|
||||||
unittest.result.traceback = traceback
|
unittest.result.traceback = traceback
|
||||||
|
|
||||||
|
|
||||||
|
def bad_cleanup1():
|
||||||
|
print('do cleanup1')
|
||||||
|
raise TypeError('bad cleanup1')
|
||||||
|
|
||||||
|
|
||||||
|
def bad_cleanup2():
|
||||||
|
print('do cleanup2')
|
||||||
|
raise ValueError('bad cleanup2')
|
||||||
|
|
||||||
|
|
||||||
class Test_TestResult(unittest.TestCase):
|
class Test_TestResult(unittest.TestCase):
|
||||||
# Note: there are not separate tests for TestResult.wasSuccessful(),
|
# Note: there are not separate tests for TestResult.wasSuccessful(),
|
||||||
# TestResult.errors, TestResult.failures, TestResult.testsRun or
|
# TestResult.errors, TestResult.failures, TestResult.testsRun or
|
||||||
|
@ -633,36 +644,320 @@ class TestOutputBuffering(unittest.TestCase):
|
||||||
self.assertEqual(result._original_stderr.getvalue(), expectedErrMessage)
|
self.assertEqual(result._original_stderr.getvalue(), expectedErrMessage)
|
||||||
self.assertMultiLineEqual(message, expectedFullMessage)
|
self.assertMultiLineEqual(message, expectedFullMessage)
|
||||||
|
|
||||||
|
def testBufferSetUp(self):
|
||||||
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
|
result.buffer = True
|
||||||
|
|
||||||
|
class Foo(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
print('set up')
|
||||||
|
1/0
|
||||||
|
def test_foo(self):
|
||||||
|
pass
|
||||||
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\nset up\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
|
self.assertEqual(len(result.errors), 1)
|
||||||
|
description = f'test_foo ({strclass(Foo)})'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(str(test_case), description)
|
||||||
|
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
|
def testBufferTearDown(self):
|
||||||
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
|
result.buffer = True
|
||||||
|
|
||||||
|
class Foo(unittest.TestCase):
|
||||||
|
def tearDown(self):
|
||||||
|
print('tear down')
|
||||||
|
1/0
|
||||||
|
def test_foo(self):
|
||||||
|
pass
|
||||||
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\ntear down\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
|
self.assertEqual(len(result.errors), 1)
|
||||||
|
description = f'test_foo ({strclass(Foo)})'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(str(test_case), description)
|
||||||
|
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
|
def testBufferDoCleanups(self):
|
||||||
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
|
result.buffer = True
|
||||||
|
|
||||||
|
class Foo(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
print('set up')
|
||||||
|
self.addCleanup(bad_cleanup1)
|
||||||
|
self.addCleanup(bad_cleanup2)
|
||||||
|
def test_foo(self):
|
||||||
|
pass
|
||||||
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\nset up\ndo cleanup2\ndo cleanup1\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
|
self.assertEqual(len(result.errors), 2)
|
||||||
|
description = f'test_foo ({strclass(Foo)})'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(str(test_case), description)
|
||||||
|
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
test_case, formatted_exc = result.errors[1]
|
||||||
|
self.assertEqual(str(test_case), description)
|
||||||
|
self.assertIn('TypeError: bad cleanup1', formatted_exc)
|
||||||
|
self.assertNotIn('ValueError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
|
def testBufferSetUp_DoCleanups(self):
|
||||||
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
|
result.buffer = True
|
||||||
|
|
||||||
|
class Foo(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
print('set up')
|
||||||
|
self.addCleanup(bad_cleanup1)
|
||||||
|
self.addCleanup(bad_cleanup2)
|
||||||
|
1/0
|
||||||
|
def test_foo(self):
|
||||||
|
pass
|
||||||
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\nset up\ndo cleanup2\ndo cleanup1\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
|
self.assertEqual(len(result.errors), 3)
|
||||||
|
description = f'test_foo ({strclass(Foo)})'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(str(test_case), description)
|
||||||
|
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||||
|
self.assertNotIn('ValueError', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
test_case, formatted_exc = result.errors[1]
|
||||||
|
self.assertEqual(str(test_case), description)
|
||||||
|
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||||
|
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
test_case, formatted_exc = result.errors[2]
|
||||||
|
self.assertEqual(str(test_case), description)
|
||||||
|
self.assertIn('TypeError: bad cleanup1', formatted_exc)
|
||||||
|
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||||
|
self.assertNotIn('ValueError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
|
def testBufferTearDown_DoCleanups(self):
|
||||||
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
|
result.buffer = True
|
||||||
|
|
||||||
|
class Foo(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
print('set up')
|
||||||
|
self.addCleanup(bad_cleanup1)
|
||||||
|
self.addCleanup(bad_cleanup2)
|
||||||
|
def tearDown(self):
|
||||||
|
print('tear down')
|
||||||
|
1/0
|
||||||
|
def test_foo(self):
|
||||||
|
pass
|
||||||
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\nset up\ntear down\ndo cleanup2\ndo cleanup1\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
|
self.assertEqual(len(result.errors), 3)
|
||||||
|
description = f'test_foo ({strclass(Foo)})'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(str(test_case), description)
|
||||||
|
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||||
|
self.assertNotIn('ValueError', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
test_case, formatted_exc = result.errors[1]
|
||||||
|
self.assertEqual(str(test_case), description)
|
||||||
|
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||||
|
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
test_case, formatted_exc = result.errors[2]
|
||||||
|
self.assertEqual(str(test_case), description)
|
||||||
|
self.assertIn('TypeError: bad cleanup1', formatted_exc)
|
||||||
|
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||||
|
self.assertNotIn('ValueError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
def testBufferSetupClass(self):
|
def testBufferSetupClass(self):
|
||||||
result = unittest.TestResult()
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
result.buffer = True
|
result.buffer = True
|
||||||
|
|
||||||
class Foo(unittest.TestCase):
|
class Foo(unittest.TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
|
print('set up class')
|
||||||
1/0
|
1/0
|
||||||
def test_foo(self):
|
def test_foo(self):
|
||||||
pass
|
pass
|
||||||
suite = unittest.TestSuite([Foo('test_foo')])
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
suite(result)
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\nset up class\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
self.assertEqual(len(result.errors), 1)
|
self.assertEqual(len(result.errors), 1)
|
||||||
|
description = f'setUpClass ({strclass(Foo)})'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
def testBufferTearDownClass(self):
|
def testBufferTearDownClass(self):
|
||||||
result = unittest.TestResult()
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
result.buffer = True
|
result.buffer = True
|
||||||
|
|
||||||
class Foo(unittest.TestCase):
|
class Foo(unittest.TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
|
print('tear down class')
|
||||||
1/0
|
1/0
|
||||||
def test_foo(self):
|
def test_foo(self):
|
||||||
pass
|
pass
|
||||||
suite = unittest.TestSuite([Foo('test_foo')])
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
suite(result)
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\ntear down class\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
self.assertEqual(len(result.errors), 1)
|
self.assertEqual(len(result.errors), 1)
|
||||||
|
description = f'tearDownClass ({strclass(Foo)})'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
|
def testBufferDoClassCleanups(self):
|
||||||
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
|
result.buffer = True
|
||||||
|
|
||||||
|
class Foo(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
print('set up class')
|
||||||
|
cls.addClassCleanup(bad_cleanup1)
|
||||||
|
cls.addClassCleanup(bad_cleanup2)
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
print('tear down class')
|
||||||
|
def test_foo(self):
|
||||||
|
pass
|
||||||
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\ntear down class\ndo cleanup2\ndo cleanup1\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
|
self.assertEqual(len(result.errors), 2)
|
||||||
|
description = f'tearDownClass ({strclass(Foo)})'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
test_case, formatted_exc = result.errors[1]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('TypeError: bad cleanup1', formatted_exc)
|
||||||
|
self.assertNotIn('ValueError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
|
def testBufferSetupClass_DoClassCleanups(self):
|
||||||
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
|
result.buffer = True
|
||||||
|
|
||||||
|
class Foo(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
print('set up class')
|
||||||
|
cls.addClassCleanup(bad_cleanup1)
|
||||||
|
cls.addClassCleanup(bad_cleanup2)
|
||||||
|
1/0
|
||||||
|
def test_foo(self):
|
||||||
|
pass
|
||||||
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\nset up class\ndo cleanup2\ndo cleanup1\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
|
self.assertEqual(len(result.errors), 3)
|
||||||
|
description = f'setUpClass ({strclass(Foo)})'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||||
|
self.assertNotIn('ValueError', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn('\nStdout:\nset up class\n', formatted_exc)
|
||||||
|
test_case, formatted_exc = result.errors[1]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||||
|
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
test_case, formatted_exc = result.errors[2]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('TypeError: bad cleanup1', formatted_exc)
|
||||||
|
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||||
|
self.assertNotIn('ValueError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
|
def testBufferTearDownClass_DoClassCleanups(self):
|
||||||
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
|
result.buffer = True
|
||||||
|
|
||||||
|
class Foo(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
print('set up class')
|
||||||
|
cls.addClassCleanup(bad_cleanup1)
|
||||||
|
cls.addClassCleanup(bad_cleanup2)
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
print('tear down class')
|
||||||
|
1/0
|
||||||
|
def test_foo(self):
|
||||||
|
pass
|
||||||
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\ntear down class\ndo cleanup2\ndo cleanup1\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
|
self.assertEqual(len(result.errors), 3)
|
||||||
|
description = f'tearDownClass ({strclass(Foo)})'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||||
|
self.assertNotIn('ValueError', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn('\nStdout:\ntear down class\n', formatted_exc)
|
||||||
|
test_case, formatted_exc = result.errors[1]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||||
|
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
test_case, formatted_exc = result.errors[2]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('TypeError: bad cleanup1', formatted_exc)
|
||||||
|
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||||
|
self.assertNotIn('ValueError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
def testBufferSetUpModule(self):
|
def testBufferSetUpModule(self):
|
||||||
result = unittest.TestResult()
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
result.buffer = True
|
result.buffer = True
|
||||||
|
|
||||||
class Foo(unittest.TestCase):
|
class Foo(unittest.TestCase):
|
||||||
|
@ -671,6 +966,7 @@ class TestOutputBuffering(unittest.TestCase):
|
||||||
class Module(object):
|
class Module(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def setUpModule():
|
def setUpModule():
|
||||||
|
print('set up module')
|
||||||
1/0
|
1/0
|
||||||
|
|
||||||
Foo.__module__ = 'Module'
|
Foo.__module__ = 'Module'
|
||||||
|
@ -678,10 +974,18 @@ class TestOutputBuffering(unittest.TestCase):
|
||||||
self.addCleanup(sys.modules.pop, 'Module')
|
self.addCleanup(sys.modules.pop, 'Module')
|
||||||
suite = unittest.TestSuite([Foo('test_foo')])
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
suite(result)
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\nset up module\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
self.assertEqual(len(result.errors), 1)
|
self.assertEqual(len(result.errors), 1)
|
||||||
|
description = 'setUpModule (Module)'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
def testBufferTearDownModule(self):
|
def testBufferTearDownModule(self):
|
||||||
result = unittest.TestResult()
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
result.buffer = True
|
result.buffer = True
|
||||||
|
|
||||||
class Foo(unittest.TestCase):
|
class Foo(unittest.TestCase):
|
||||||
|
@ -690,6 +994,7 @@ class TestOutputBuffering(unittest.TestCase):
|
||||||
class Module(object):
|
class Module(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def tearDownModule():
|
def tearDownModule():
|
||||||
|
print('tear down module')
|
||||||
1/0
|
1/0
|
||||||
|
|
||||||
Foo.__module__ = 'Module'
|
Foo.__module__ = 'Module'
|
||||||
|
@ -697,7 +1002,124 @@ class TestOutputBuffering(unittest.TestCase):
|
||||||
self.addCleanup(sys.modules.pop, 'Module')
|
self.addCleanup(sys.modules.pop, 'Module')
|
||||||
suite = unittest.TestSuite([Foo('test_foo')])
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
suite(result)
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\ntear down module\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
self.assertEqual(len(result.errors), 1)
|
self.assertEqual(len(result.errors), 1)
|
||||||
|
description = 'tearDownModule (Module)'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
|
def testBufferDoModuleCleanups(self):
|
||||||
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
|
result.buffer = True
|
||||||
|
|
||||||
|
class Foo(unittest.TestCase):
|
||||||
|
def test_foo(self):
|
||||||
|
pass
|
||||||
|
class Module(object):
|
||||||
|
@staticmethod
|
||||||
|
def setUpModule():
|
||||||
|
print('set up module')
|
||||||
|
unittest.addModuleCleanup(bad_cleanup1)
|
||||||
|
unittest.addModuleCleanup(bad_cleanup2)
|
||||||
|
|
||||||
|
Foo.__module__ = 'Module'
|
||||||
|
sys.modules['Module'] = Module
|
||||||
|
self.addCleanup(sys.modules.pop, 'Module')
|
||||||
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\ndo cleanup2\ndo cleanup1\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
|
self.assertEqual(len(result.errors), 1)
|
||||||
|
description = 'tearDownModule (Module)'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
|
def testBufferSetUpModule_DoModuleCleanups(self):
|
||||||
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
|
result.buffer = True
|
||||||
|
|
||||||
|
class Foo(unittest.TestCase):
|
||||||
|
def test_foo(self):
|
||||||
|
pass
|
||||||
|
class Module(object):
|
||||||
|
@staticmethod
|
||||||
|
def setUpModule():
|
||||||
|
print('set up module')
|
||||||
|
unittest.addModuleCleanup(bad_cleanup1)
|
||||||
|
unittest.addModuleCleanup(bad_cleanup2)
|
||||||
|
1/0
|
||||||
|
|
||||||
|
Foo.__module__ = 'Module'
|
||||||
|
sys.modules['Module'] = Module
|
||||||
|
self.addCleanup(sys.modules.pop, 'Module')
|
||||||
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\nset up module\ndo cleanup2\ndo cleanup1\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
|
self.assertEqual(len(result.errors), 2)
|
||||||
|
description = 'setUpModule (Module)'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||||
|
self.assertNotIn('ValueError', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn('\nStdout:\nset up module\n', formatted_exc)
|
||||||
|
test_case, formatted_exc = result.errors[1]
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||||
|
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
|
def testBufferTearDownModule_DoModuleCleanups(self):
|
||||||
|
with captured_stdout() as stdout:
|
||||||
|
result = unittest.TestResult()
|
||||||
|
result.buffer = True
|
||||||
|
|
||||||
|
class Foo(unittest.TestCase):
|
||||||
|
def test_foo(self):
|
||||||
|
pass
|
||||||
|
class Module(object):
|
||||||
|
@staticmethod
|
||||||
|
def setUpModule():
|
||||||
|
print('set up module')
|
||||||
|
unittest.addModuleCleanup(bad_cleanup1)
|
||||||
|
unittest.addModuleCleanup(bad_cleanup2)
|
||||||
|
@staticmethod
|
||||||
|
def tearDownModule():
|
||||||
|
print('tear down module')
|
||||||
|
1/0
|
||||||
|
|
||||||
|
Foo.__module__ = 'Module'
|
||||||
|
sys.modules['Module'] = Module
|
||||||
|
self.addCleanup(sys.modules.pop, 'Module')
|
||||||
|
suite = unittest.TestSuite([Foo('test_foo')])
|
||||||
|
suite(result)
|
||||||
|
expected_out = '\nStdout:\ntear down module\ndo cleanup2\ndo cleanup1\n'
|
||||||
|
self.assertEqual(stdout.getvalue(), expected_out)
|
||||||
|
self.assertEqual(len(result.errors), 2)
|
||||||
|
description = 'tearDownModule (Module)'
|
||||||
|
test_case, formatted_exc = result.errors[0]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('ZeroDivisionError: division by zero', formatted_exc)
|
||||||
|
self.assertNotIn('ValueError', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn('\nStdout:\ntear down module\n', formatted_exc)
|
||||||
|
test_case, formatted_exc = result.errors[1]
|
||||||
|
self.assertEqual(test_case.description, description)
|
||||||
|
self.assertIn('ValueError: bad cleanup2', formatted_exc)
|
||||||
|
self.assertNotIn('ZeroDivisionError', formatted_exc)
|
||||||
|
self.assertNotIn('TypeError', formatted_exc)
|
||||||
|
self.assertIn(expected_out, formatted_exc)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -222,14 +222,42 @@ class TestClassCleanup(unittest.TestCase):
|
||||||
self.assertEqual(ordering,
|
self.assertEqual(ordering,
|
||||||
['setUpClass', 'test', 'tearDownClass', 'cleanup_good'])
|
['setUpClass', 'test', 'tearDownClass', 'cleanup_good'])
|
||||||
|
|
||||||
def test_debug_executes_classCleanUp(self):
|
def test_run_class_cleanUp_without_tearDownClass(self):
|
||||||
ordering = []
|
ordering = []
|
||||||
|
blowUp = True
|
||||||
|
|
||||||
class TestableTest(unittest.TestCase):
|
class TestableTest(unittest.TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
ordering.append('setUpClass')
|
ordering.append('setUpClass')
|
||||||
cls.addClassCleanup(cleanup, ordering)
|
cls.addClassCleanup(cleanup, ordering)
|
||||||
|
if blowUp:
|
||||||
|
raise Exception()
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test')
|
||||||
|
@classmethod
|
||||||
|
@property
|
||||||
|
def tearDownClass(cls):
|
||||||
|
raise AttributeError
|
||||||
|
|
||||||
|
runTests(TestableTest)
|
||||||
|
self.assertEqual(ordering, ['setUpClass', 'cleanup_good'])
|
||||||
|
|
||||||
|
ordering = []
|
||||||
|
blowUp = False
|
||||||
|
runTests(TestableTest)
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpClass', 'test', 'cleanup_good'])
|
||||||
|
|
||||||
|
def test_debug_executes_classCleanUp(self):
|
||||||
|
ordering = []
|
||||||
|
blowUp = False
|
||||||
|
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
ordering.append('setUpClass')
|
||||||
|
cls.addClassCleanup(cleanup, ordering, blowUp=blowUp)
|
||||||
def testNothing(self):
|
def testNothing(self):
|
||||||
ordering.append('test')
|
ordering.append('test')
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -241,6 +269,48 @@ class TestClassCleanup(unittest.TestCase):
|
||||||
self.assertEqual(ordering,
|
self.assertEqual(ordering,
|
||||||
['setUpClass', 'test', 'tearDownClass', 'cleanup_good'])
|
['setUpClass', 'test', 'tearDownClass', 'cleanup_good'])
|
||||||
|
|
||||||
|
ordering = []
|
||||||
|
blowUp = True
|
||||||
|
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||||
|
with self.assertRaises(Exception) as cm:
|
||||||
|
suite.debug()
|
||||||
|
self.assertEqual(str(cm.exception), 'CleanUpExc')
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpClass', 'test', 'tearDownClass', 'cleanup_exc'])
|
||||||
|
|
||||||
|
def test_debug_executes_classCleanUp_when_teardown_exception(self):
|
||||||
|
ordering = []
|
||||||
|
blowUp = False
|
||||||
|
|
||||||
|
class TestableTest(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
ordering.append('setUpClass')
|
||||||
|
cls.addClassCleanup(cleanup, ordering, blowUp=blowUp)
|
||||||
|
def testNothing(self):
|
||||||
|
ordering.append('test')
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
raise Exception('TearDownClassExc')
|
||||||
|
|
||||||
|
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||||
|
with self.assertRaises(Exception) as cm:
|
||||||
|
suite.debug()
|
||||||
|
self.assertEqual(str(cm.exception), 'TearDownClassExc')
|
||||||
|
self.assertEqual(ordering, ['setUpClass', 'test'])
|
||||||
|
self.assertTrue(TestableTest._class_cleanups)
|
||||||
|
TestableTest._class_cleanups.clear()
|
||||||
|
|
||||||
|
ordering = []
|
||||||
|
blowUp = True
|
||||||
|
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||||
|
with self.assertRaises(Exception) as cm:
|
||||||
|
suite.debug()
|
||||||
|
self.assertEqual(str(cm.exception), 'TearDownClassExc')
|
||||||
|
self.assertEqual(ordering, ['setUpClass', 'test'])
|
||||||
|
self.assertTrue(TestableTest._class_cleanups)
|
||||||
|
TestableTest._class_cleanups.clear()
|
||||||
|
|
||||||
def test_doClassCleanups_with_errors_addClassCleanUp(self):
|
def test_doClassCleanups_with_errors_addClassCleanUp(self):
|
||||||
class TestableTest(unittest.TestCase):
|
class TestableTest(unittest.TestCase):
|
||||||
def testNothing(self):
|
def testNothing(self):
|
||||||
|
@ -332,6 +402,7 @@ class TestClassCleanup(unittest.TestCase):
|
||||||
self.assertEqual(ordering,
|
self.assertEqual(ordering,
|
||||||
['setUpClass', 'setUp', 'test',
|
['setUpClass', 'setUp', 'test',
|
||||||
'tearDownClass', 'cleanup_exc'])
|
'tearDownClass', 'cleanup_exc'])
|
||||||
|
|
||||||
ordering = []
|
ordering = []
|
||||||
class_blow_up = True
|
class_blow_up = True
|
||||||
method_blow_up = False
|
method_blow_up = False
|
||||||
|
@ -355,6 +426,26 @@ class TestClassCleanup(unittest.TestCase):
|
||||||
['setUpClass', 'setUp', 'tearDownClass',
|
['setUpClass', 'setUp', 'tearDownClass',
|
||||||
'cleanup_exc'])
|
'cleanup_exc'])
|
||||||
|
|
||||||
|
def test_with_errors_in_tearDownClass(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')
|
||||||
|
raise Exception('TearDownExc')
|
||||||
|
|
||||||
|
result = runTests(TestableTest)
|
||||||
|
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||||
|
'Exception: TearDownExc')
|
||||||
|
self.assertEqual(ordering,
|
||||||
|
['setUpClass', 'test', 'tearDownClass', 'cleanup_good'])
|
||||||
|
|
||||||
|
|
||||||
class TestModuleCleanUp(unittest.TestCase):
|
class TestModuleCleanUp(unittest.TestCase):
|
||||||
def test_add_and_do_ModuleCleanup(self):
|
def test_add_and_do_ModuleCleanup(self):
|
||||||
|
@ -532,13 +623,69 @@ class TestModuleCleanUp(unittest.TestCase):
|
||||||
'tearDownModule2', 'cleanup_good'])
|
'tearDownModule2', 'cleanup_good'])
|
||||||
self.assertEqual(unittest.case._module_cleanups, [])
|
self.assertEqual(unittest.case._module_cleanups, [])
|
||||||
|
|
||||||
def test_debug_module_executes_cleanUp(self):
|
def test_run_module_cleanUp_without_teardown(self):
|
||||||
ordering = []
|
ordering = []
|
||||||
class Module(object):
|
class Module(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def setUpModule():
|
def setUpModule():
|
||||||
ordering.append('setUpModule')
|
ordering.append('setUpModule')
|
||||||
unittest.addModuleCleanup(cleanup, ordering)
|
unittest.addModuleCleanup(cleanup, ordering)
|
||||||
|
|
||||||
|
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
|
||||||
|
runTests(TestableTest)
|
||||||
|
self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
|
||||||
|
'tearDownClass', 'cleanup_good'])
|
||||||
|
self.assertEqual(unittest.case._module_cleanups, [])
|
||||||
|
|
||||||
|
def test_run_module_cleanUp_when_teardown_exception(self):
|
||||||
|
ordering = []
|
||||||
|
class Module(object):
|
||||||
|
@staticmethod
|
||||||
|
def setUpModule():
|
||||||
|
ordering.append('setUpModule')
|
||||||
|
unittest.addModuleCleanup(cleanup, ordering)
|
||||||
|
@staticmethod
|
||||||
|
def tearDownModule():
|
||||||
|
raise Exception('CleanUpExc')
|
||||||
|
|
||||||
|
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(result.errors[0][1].splitlines()[-1],
|
||||||
|
'Exception: CleanUpExc')
|
||||||
|
self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
|
||||||
|
'tearDownClass', 'cleanup_good'])
|
||||||
|
self.assertEqual(unittest.case._module_cleanups, [])
|
||||||
|
|
||||||
|
def test_debug_module_executes_cleanUp(self):
|
||||||
|
ordering = []
|
||||||
|
blowUp = False
|
||||||
|
class Module(object):
|
||||||
|
@staticmethod
|
||||||
|
def setUpModule():
|
||||||
|
ordering.append('setUpModule')
|
||||||
|
unittest.addModuleCleanup(cleanup, ordering, blowUp=blowUp)
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def tearDownModule():
|
def tearDownModule():
|
||||||
ordering.append('tearDownModule')
|
ordering.append('tearDownModule')
|
||||||
|
@ -562,6 +709,60 @@ class TestModuleCleanUp(unittest.TestCase):
|
||||||
'tearDownModule', 'cleanup_good'])
|
'tearDownModule', 'cleanup_good'])
|
||||||
self.assertEqual(unittest.case._module_cleanups, [])
|
self.assertEqual(unittest.case._module_cleanups, [])
|
||||||
|
|
||||||
|
ordering = []
|
||||||
|
blowUp = True
|
||||||
|
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||||
|
with self.assertRaises(Exception) as cm:
|
||||||
|
suite.debug()
|
||||||
|
self.assertEqual(str(cm.exception), 'CleanUpExc')
|
||||||
|
self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
|
||||||
|
'tearDownClass', 'tearDownModule', 'cleanup_exc'])
|
||||||
|
self.assertEqual(unittest.case._module_cleanups, [])
|
||||||
|
|
||||||
|
def test_debug_module_cleanUp_when_teardown_exception(self):
|
||||||
|
ordering = []
|
||||||
|
blowUp = False
|
||||||
|
class Module(object):
|
||||||
|
@staticmethod
|
||||||
|
def setUpModule():
|
||||||
|
ordering.append('setUpModule')
|
||||||
|
unittest.addModuleCleanup(cleanup, ordering, blowUp=blowUp)
|
||||||
|
@staticmethod
|
||||||
|
def tearDownModule():
|
||||||
|
raise Exception('TearDownModuleExc')
|
||||||
|
|
||||||
|
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)
|
||||||
|
with self.assertRaises(Exception) as cm:
|
||||||
|
suite.debug()
|
||||||
|
self.assertEqual(str(cm.exception), 'TearDownModuleExc')
|
||||||
|
self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
|
||||||
|
'tearDownClass'])
|
||||||
|
self.assertTrue(unittest.case._module_cleanups)
|
||||||
|
unittest.case._module_cleanups.clear()
|
||||||
|
|
||||||
|
ordering = []
|
||||||
|
blowUp = True
|
||||||
|
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestableTest)
|
||||||
|
with self.assertRaises(Exception) as cm:
|
||||||
|
suite.debug()
|
||||||
|
self.assertEqual(str(cm.exception), 'TearDownModuleExc')
|
||||||
|
self.assertEqual(ordering, ['setUpModule', 'setUpClass', 'test',
|
||||||
|
'tearDownClass'])
|
||||||
|
self.assertTrue(unittest.case._module_cleanups)
|
||||||
|
unittest.case._module_cleanups.clear()
|
||||||
|
|
||||||
def test_addClassCleanup_arg_errors(self):
|
def test_addClassCleanup_arg_errors(self):
|
||||||
cleanups = []
|
cleanups = []
|
||||||
def cleanup(*args, **kwargs):
|
def cleanup(*args, **kwargs):
|
||||||
|
@ -717,9 +918,9 @@ class TestModuleCleanUp(unittest.TestCase):
|
||||||
method_blow_up = False
|
method_blow_up = False
|
||||||
result = runTests(TestableTest)
|
result = runTests(TestableTest)
|
||||||
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
self.assertEqual(result.errors[0][1].splitlines()[-1],
|
||||||
'Exception: CleanUpExc')
|
|
||||||
self.assertEqual(result.errors[1][1].splitlines()[-1],
|
|
||||||
'Exception: ModuleExc')
|
'Exception: ModuleExc')
|
||||||
|
self.assertEqual(result.errors[1][1].splitlines()[-1],
|
||||||
|
'Exception: CleanUpExc')
|
||||||
self.assertEqual(ordering, ['setUpModule', 'cleanup_exc'])
|
self.assertEqual(ordering, ['setUpModule', 'cleanup_exc'])
|
||||||
|
|
||||||
ordering = []
|
ordering = []
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
Fix bugs in cleaning up classes and modules in :mod:`unittest`:
|
||||||
|
|
||||||
|
* Functions registered with :func:`~unittest.addModuleCleanup` were not called unless the user defines ``tearDownModule()`` in their test module.
|
||||||
|
* Functions registered with :meth:`~unittest.TestCase.addClassCleanup` were not called if ``tearDownClass`` is set to ``None``.
|
||||||
|
* Buffering in :class:`~unittest.TestResult` did not work with functions registered with ``addClassCleanup()`` and ``addModuleCleanup()``.
|
||||||
|
* Errors in functions registered with ``addClassCleanup()`` and ``addModuleCleanup()`` were not handled correctly in buffered and debug modes.
|
||||||
|
* Errors in ``setUpModule()`` and functions registered with ``addModuleCleanup()`` were reported in wrong order.
|
||||||
|
* And several lesser bugs.
|
Loading…
Add table
Add a link
Reference in a new issue