summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Foord <fuzzyman@voidspace.org.uk>2010-06-08 22:44:52 (GMT)
committerMichael Foord <fuzzyman@voidspace.org.uk>2010-06-08 22:44:52 (GMT)
commit0fedb28951034e0ee3c5cd4761257d85a5fd4da2 (patch)
treee5a2dc058a09a8c626475352f4ca0598110bd9c1
parentd7afd31a9bef6e0498e8fce646a2d4e8e8576e87 (diff)
downloadcpython-0fedb28951034e0ee3c5cd4761257d85a5fd4da2.zip
cpython-0fedb28951034e0ee3c5cd4761257d85a5fd4da2.tar.gz
cpython-0fedb28951034e0ee3c5cd4761257d85a5fd4da2.tar.bz2
Issue 8948. cleanup functions are not run by unittest.TestCase.debug(), plus class and module teardowns are not run by unittest.TestSuite.debug().
-rw-r--r--Lib/unittest/case.py3
-rw-r--r--Lib/unittest/suite.py28
-rw-r--r--Lib/unittest/test/test_runner.py25
-rw-r--r--Lib/unittest/test/test_setups.py62
4 files changed, 116 insertions, 2 deletions
diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py
index 8341b88..b609caf 100644
--- a/Lib/unittest/case.py
+++ b/Lib/unittest/case.py
@@ -380,6 +380,9 @@ class TestCase(object):
self.setUp()
getattr(self, self._testMethodName)()
self.tearDown()
+ while self._cleanups:
+ function, args, kwargs = self._cleanups.pop(-1)
+ function(*args, **kwargs)
def skipTest(self, reason):
"""Skip this test."""
diff --git a/Lib/unittest/suite.py b/Lib/unittest/suite.py
index bed9044..04d35b8 100644
--- a/Lib/unittest/suite.py
+++ b/Lib/unittest/suite.py
@@ -87,9 +87,16 @@ class TestSuite(BaseTestSuite):
self._handleModuleTearDown(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
- def _wrapped_run(self, result):
+ def _wrapped_run(self, result, debug=False):
for test in self:
if result.shouldStop:
break
@@ -106,8 +113,10 @@ class TestSuite(BaseTestSuite):
if hasattr(test, '_wrapped_run'):
test._wrapped_run(result)
- else:
+ elif not debug:
test(result)
+ else:
+ test.debug()
def _handleClassSetUp(self, test, result):
previousClass = getattr(result, '_previousTestClass', None)
@@ -131,6 +140,8 @@ class TestSuite(BaseTestSuite):
try:
setUpClass()
except Exception as e:
+ if isinstance(result, _DebugResult):
+ raise
currentClass._classSetupFailed = True
className = util.strclass(currentClass)
errorName = 'setUpClass (%s)' % className
@@ -163,6 +174,8 @@ class TestSuite(BaseTestSuite):
try:
setUpModule()
except Exception, e:
+ if isinstance(result, _DebugResult):
+ raise
result._moduleSetUpFailed = True
errorName = 'setUpModule (%s)' % currentModule
self._addClassOrModuleLevelException(result, e, errorName)
@@ -192,6 +205,8 @@ class TestSuite(BaseTestSuite):
try:
tearDownModule()
except Exception as e:
+ if isinstance(result, _DebugResult):
+ raise
errorName = 'tearDownModule (%s)' % previousModule
self._addClassOrModuleLevelException(result, e, errorName)
@@ -212,6 +227,8 @@ class TestSuite(BaseTestSuite):
try:
tearDownClass()
except Exception, e:
+ if isinstance(result, _DebugResult):
+ raise
className = util.strclass(previousClass)
errorName = 'tearDownClass (%s)' % className
self._addClassOrModuleLevelException(result, e, errorName)
@@ -262,3 +279,10 @@ def _isnotsuite(test):
except TypeError:
return True
return False
+
+
+class _DebugResult(object):
+ "Used by the TestSuite to hold previous class when running in debug."
+ _previousTestClass = None
+ _moduleSetUpFailed = False
+ shouldStop = False
diff --git a/Lib/unittest/test/test_runner.py b/Lib/unittest/test/test_runner.py
index 7e606ca..6df6a9c 100644
--- a/Lib/unittest/test/test_runner.py
+++ b/Lib/unittest/test/test_runner.py
@@ -111,6 +111,31 @@ class TestCleanUp(unittest.TestCase):
test.run(result)
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):
"""Tests for TextTestRunner."""
diff --git a/Lib/unittest/test/test_setups.py b/Lib/unittest/test/test_setups.py
index aff7ab2..a9e1ae9 100644
--- a/Lib/unittest/test/test_setups.py
+++ b/Lib/unittest/test/test_setups.py
@@ -439,6 +439,68 @@ class TestSetups(unittest.TestCase):
skipped = result.skipped[0][0]
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__':
unittest.main()