Commit 0fedb289 authored by Michael Foord's avatar Michael Foord

Issue 8948. cleanup functions are not run by unittest.TestCase.debug(), plus...

Issue 8948. cleanup functions are not run by unittest.TestCase.debug(), plus class and module teardowns are not run by unittest.TestSuite.debug().
parent d7afd31a
...@@ -380,6 +380,9 @@ class TestCase(object): ...@@ -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."""
......
...@@ -87,9 +87,16 @@ class TestSuite(BaseTestSuite): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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
...@@ -111,6 +111,31 @@ class TestCleanUp(unittest.TestCase): ...@@ -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."""
......
...@@ -439,6 +439,68 @@ class TestSetups(unittest.TestCase): ...@@ -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()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment