Issue 8948. cleanup functions are not run by unittest.TestCase.debug(), plus class and module teardowns are not run by unittest.TestSuite.debug().

This commit is contained in:
Michael Foord 2010-06-08 22:44:52 +00:00
parent d7afd31a9b
commit 0fedb28951
4 changed files with 116 additions and 2 deletions

View File

@ -380,6 +380,9 @@ class TestCase(object):
self.setUp() self.setUp()
getattr(self, self._testMethodName)() getattr(self, self._testMethodName)()
self.tearDown() self.tearDown()
while self._cleanups:
function, args, kwargs = self._cleanups.pop(-1)
function(*args, **kwargs)
def skipTest(self, reason): def skipTest(self, reason):
"""Skip this test.""" """Skip this test."""

View File

@ -87,9 +87,16 @@ class TestSuite(BaseTestSuite):
self._handleModuleTearDown(result) self._handleModuleTearDown(result)
return result return result
def debug(self):
"""Run the tests without collecting errors in a TestResult"""
debug = _DebugResult()
self._wrapped_run(debug, True)
self._tearDownPreviousClass(None, debug)
self._handleModuleTearDown(debug)
################################ ################################
# private methods # private methods
def _wrapped_run(self, result): def _wrapped_run(self, result, debug=False):
for test in self: for test in self:
if result.shouldStop: if result.shouldStop:
break break
@ -106,8 +113,10 @@ class TestSuite(BaseTestSuite):
if hasattr(test, '_wrapped_run'): if hasattr(test, '_wrapped_run'):
test._wrapped_run(result) test._wrapped_run(result)
else: elif not debug:
test(result) test(result)
else:
test.debug()
def _handleClassSetUp(self, test, result): def _handleClassSetUp(self, test, result):
previousClass = getattr(result, '_previousTestClass', None) previousClass = getattr(result, '_previousTestClass', None)
@ -131,6 +140,8 @@ class TestSuite(BaseTestSuite):
try: try:
setUpClass() setUpClass()
except Exception as e: except Exception as e:
if isinstance(result, _DebugResult):
raise
currentClass._classSetupFailed = True currentClass._classSetupFailed = True
className = util.strclass(currentClass) className = util.strclass(currentClass)
errorName = 'setUpClass (%s)' % className errorName = 'setUpClass (%s)' % className
@ -163,6 +174,8 @@ class TestSuite(BaseTestSuite):
try: try:
setUpModule() setUpModule()
except Exception, e: except Exception, e:
if isinstance(result, _DebugResult):
raise
result._moduleSetUpFailed = True result._moduleSetUpFailed = True
errorName = 'setUpModule (%s)' % currentModule errorName = 'setUpModule (%s)' % currentModule
self._addClassOrModuleLevelException(result, e, errorName) self._addClassOrModuleLevelException(result, e, errorName)
@ -192,6 +205,8 @@ class TestSuite(BaseTestSuite):
try: try:
tearDownModule() tearDownModule()
except Exception as e: except Exception as e:
if isinstance(result, _DebugResult):
raise
errorName = 'tearDownModule (%s)' % previousModule errorName = 'tearDownModule (%s)' % previousModule
self._addClassOrModuleLevelException(result, e, errorName) self._addClassOrModuleLevelException(result, e, errorName)
@ -212,6 +227,8 @@ class TestSuite(BaseTestSuite):
try: try:
tearDownClass() tearDownClass()
except Exception, e: except Exception, e:
if isinstance(result, _DebugResult):
raise
className = util.strclass(previousClass) className = util.strclass(previousClass)
errorName = 'tearDownClass (%s)' % className errorName = 'tearDownClass (%s)' % className
self._addClassOrModuleLevelException(result, e, errorName) self._addClassOrModuleLevelException(result, e, errorName)
@ -262,3 +279,10 @@ def _isnotsuite(test):
except TypeError: except TypeError:
return True return True
return False return False
class _DebugResult(object):
"Used by the TestSuite to hold previous class when running in debug."
_previousTestClass = None
_moduleSetUpFailed = False
shouldStop = False

View File

@ -111,6 +111,31 @@ class TestCleanUp(unittest.TestCase):
test.run(result) test.run(result)
self.assertEqual(ordering, ['setUp', 'cleanup1']) self.assertEqual(ordering, ['setUp', 'cleanup1'])
def testTestCaseDebugExecutesCleanups(self):
ordering = []
class TestableTest(unittest.TestCase):
def setUp(self):
ordering.append('setUp')
self.addCleanup(cleanup1)
def testNothing(self):
ordering.append('test')
def tearDown(self):
ordering.append('tearDown')
test = TestableTest('testNothing')
def cleanup1():
ordering.append('cleanup1')
test.addCleanup(cleanup2)
def cleanup2():
ordering.append('cleanup2')
test.debug()
self.assertEqual(ordering, ['setUp', 'test', 'tearDown', 'cleanup1', 'cleanup2'])
class Test_TextTestRunner(unittest.TestCase): class Test_TextTestRunner(unittest.TestCase):
"""Tests for TextTestRunner.""" """Tests for TextTestRunner."""

View File

@ -439,6 +439,68 @@ class TestSetups(unittest.TestCase):
skipped = result.skipped[0][0] skipped = result.skipped[0][0]
self.assertEqual(str(skipped), 'setUpModule (Module)') self.assertEqual(str(skipped), 'setUpModule (Module)')
def test_suite_debug_executes_setups_and_teardowns(self):
ordering = []
class Module(object):
@staticmethod
def setUpModule():
ordering.append('setUpModule')
@staticmethod
def tearDownModule():
ordering.append('tearDownModule')
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls):
ordering.append('setUpClass')
@classmethod
def tearDownClass(cls):
ordering.append('tearDownClass')
def test_something(self):
ordering.append('test_something')
Test.__module__ = 'Module'
sys.modules['Module'] = Module
suite = unittest.defaultTestLoader.loadTestsFromTestCase(Test)
suite.debug()
expectedOrder = ['setUpModule', 'setUpClass', 'test_something', 'tearDownClass', 'tearDownModule']
self.assertEqual(ordering, expectedOrder)
def test_suite_debug_propagates_exceptions(self):
class Module(object):
@staticmethod
def setUpModule():
if phase == 0:
raise Exception('setUpModule')
@staticmethod
def tearDownModule():
if phase == 1:
raise Exception('tearDownModule')
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls):
if phase == 2:
raise Exception('setUpClass')
@classmethod
def tearDownClass(cls):
if phase == 3:
raise Exception('tearDownClass')
def test_something(self):
if phase == 4:
raise Exception('test_something')
Test.__module__ = 'Module'
sys.modules['Module'] = Module
suite = unittest.defaultTestLoader.loadTestsFromTestCase(Test)
messages = ('setUpModule', 'tearDownModule', 'setUpClass', 'tearDownClass', 'test_something')
for phase, msg in enumerate(messages):
with self.assertRaisesRegexp(Exception, msg):
suite.debug()
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()