Commit 42ec7cb1 authored by Michael Foord's avatar Michael Foord

Issue #10979. unittest stdout buffering now works with class and module setup and teardown.

parent b2760a0b
...@@ -59,6 +59,9 @@ class TestResult(object): ...@@ -59,6 +59,9 @@ class TestResult(object):
"Called when the given test is about to be run" "Called when the given test is about to be run"
self.testsRun += 1 self.testsRun += 1
self._mirrorOutput = False self._mirrorOutput = False
self._setupStdout()
def _setupStdout(self):
if self.buffer: if self.buffer:
if self._stderr_buffer is None: if self._stderr_buffer is None:
self._stderr_buffer = io.StringIO() self._stderr_buffer = io.StringIO()
...@@ -74,6 +77,10 @@ class TestResult(object): ...@@ -74,6 +77,10 @@ class TestResult(object):
def stopTest(self, test): def stopTest(self, test):
"""Called when the given test has been run""" """Called when the given test has been run"""
self._restoreStdout()
self._mirrorOutput = False
def _restoreStdout(self):
if self.buffer: if self.buffer:
if self._mirrorOutput: if self._mirrorOutput:
output = sys.stdout.getvalue() output = sys.stdout.getvalue()
...@@ -93,7 +100,6 @@ class TestResult(object): ...@@ -93,7 +100,6 @@ class TestResult(object):
self._stdout_buffer.truncate() self._stdout_buffer.truncate()
self._stderr_buffer.seek(0) self._stderr_buffer.seek(0)
self._stderr_buffer.truncate() self._stderr_buffer.truncate()
self._mirrorOutput = False
def stopTestRun(self): def stopTestRun(self):
"""Called once after all tests are executed. """Called once after all tests are executed.
......
...@@ -8,6 +8,11 @@ from . import util ...@@ -8,6 +8,11 @@ from . import util
__unittest = True __unittest = True
def _call_if_exists(parent, attr):
func = getattr(parent, attr, lambda: None)
func()
class BaseTestSuite(object): class BaseTestSuite(object):
"""A simple test suite that doesn't provide class or module shared fixtures. """A simple test suite that doesn't provide class or module shared fixtures.
""" """
...@@ -133,6 +138,7 @@ class TestSuite(BaseTestSuite): ...@@ -133,6 +138,7 @@ class TestSuite(BaseTestSuite):
setUpClass = getattr(currentClass, 'setUpClass', None) setUpClass = getattr(currentClass, 'setUpClass', None)
if setUpClass is not None: if setUpClass is not None:
_call_if_exists(result, '_setupStdout')
try: try:
setUpClass() setUpClass()
except Exception as e: except Exception as e:
...@@ -142,6 +148,8 @@ class TestSuite(BaseTestSuite): ...@@ -142,6 +148,8 @@ class TestSuite(BaseTestSuite):
className = util.strclass(currentClass) className = util.strclass(currentClass)
errorName = 'setUpClass (%s)' % className errorName = 'setUpClass (%s)' % className
self._addClassOrModuleLevelException(result, e, errorName) self._addClassOrModuleLevelException(result, e, errorName)
finally:
_call_if_exists(result, '_restoreStdout')
def _get_previous_module(self, result): def _get_previous_module(self, result):
previousModule = None previousModule = None
...@@ -167,6 +175,7 @@ class TestSuite(BaseTestSuite): ...@@ -167,6 +175,7 @@ class TestSuite(BaseTestSuite):
return return
setUpModule = getattr(module, 'setUpModule', None) setUpModule = getattr(module, 'setUpModule', None)
if setUpModule is not None: if setUpModule is not None:
_call_if_exists(result, '_setupStdout')
try: try:
setUpModule() setUpModule()
except Exception as e: except Exception as e:
...@@ -175,6 +184,8 @@ class TestSuite(BaseTestSuite): ...@@ -175,6 +184,8 @@ class TestSuite(BaseTestSuite):
result._moduleSetUpFailed = True result._moduleSetUpFailed = True
errorName = 'setUpModule (%s)' % currentModule errorName = 'setUpModule (%s)' % currentModule
self._addClassOrModuleLevelException(result, e, errorName) self._addClassOrModuleLevelException(result, e, errorName)
finally:
_call_if_exists(result, '_restoreStdout')
def _addClassOrModuleLevelException(self, result, exception, errorName): def _addClassOrModuleLevelException(self, result, exception, errorName):
error = _ErrorHolder(errorName) error = _ErrorHolder(errorName)
...@@ -198,6 +209,7 @@ class TestSuite(BaseTestSuite): ...@@ -198,6 +209,7 @@ class TestSuite(BaseTestSuite):
tearDownModule = getattr(module, 'tearDownModule', None) tearDownModule = getattr(module, 'tearDownModule', None)
if tearDownModule is not None: if tearDownModule is not None:
_call_if_exists(result, '_setupStdout')
try: try:
tearDownModule() tearDownModule()
except Exception as e: except Exception as e:
...@@ -205,6 +217,8 @@ class TestSuite(BaseTestSuite): ...@@ -205,6 +217,8 @@ class TestSuite(BaseTestSuite):
raise raise
errorName = 'tearDownModule (%s)' % previousModule errorName = 'tearDownModule (%s)' % previousModule
self._addClassOrModuleLevelException(result, e, errorName) self._addClassOrModuleLevelException(result, e, errorName)
finally:
_call_if_exists(result, '_restoreStdout')
def _tearDownPreviousClass(self, test, result): def _tearDownPreviousClass(self, test, result):
previousClass = getattr(result, '_previousTestClass', None) previousClass = getattr(result, '_previousTestClass', None)
...@@ -220,6 +234,7 @@ class TestSuite(BaseTestSuite): ...@@ -220,6 +234,7 @@ class TestSuite(BaseTestSuite):
tearDownClass = getattr(previousClass, 'tearDownClass', None) tearDownClass = getattr(previousClass, 'tearDownClass', None)
if tearDownClass is not None: if tearDownClass is not None:
_call_if_exists(result, '_setupStdout')
try: try:
tearDownClass() tearDownClass()
except Exception as e: except Exception as e:
...@@ -228,7 +243,8 @@ class TestSuite(BaseTestSuite): ...@@ -228,7 +243,8 @@ class TestSuite(BaseTestSuite):
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)
finally:
_call_if_exists(result, '_restoreStdout')
class _ErrorHolder(object): class _ErrorHolder(object):
......
...@@ -497,5 +497,72 @@ class TestOutputBuffering(unittest.TestCase): ...@@ -497,5 +497,72 @@ 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 testBufferSetupClass(self):
result = unittest.TestResult()
result.buffer = True
class Foo(unittest.TestCase):
@classmethod
def setUpClass(cls):
1/0
def test_foo(self):
pass
suite = unittest.TestSuite([Foo('test_foo')])
suite(result)
self.assertEqual(len(result.errors), 1)
def testBufferTearDownClass(self):
result = unittest.TestResult()
result.buffer = True
class Foo(unittest.TestCase):
@classmethod
def tearDownClass(cls):
1/0
def test_foo(self):
pass
suite = unittest.TestSuite([Foo('test_foo')])
suite(result)
self.assertEqual(len(result.errors), 1)
def testBufferSetUpModule(self):
result = unittest.TestResult()
result.buffer = True
class Foo(unittest.TestCase):
def test_foo(self):
pass
class Module(object):
@staticmethod
def setUpModule():
1/0
Foo.__module__ = 'Module'
sys.modules['Module'] = Module
self.addCleanup(sys.modules.pop, 'Module')
suite = unittest.TestSuite([Foo('test_foo')])
suite(result)
self.assertEqual(len(result.errors), 1)
def testBufferTearDownModule(self):
result = unittest.TestResult()
result.buffer = True
class Foo(unittest.TestCase):
def test_foo(self):
pass
class Module(object):
@staticmethod
def tearDownModule():
1/0
Foo.__module__ = 'Module'
sys.modules['Module'] = Module
self.addCleanup(sys.modules.pop, 'Module')
suite = unittest.TestSuite([Foo('test_foo')])
suite(result)
self.assertEqual(len(result.errors), 1)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -10,6 +10,9 @@ What's New in Python 3.2.1? ...@@ -10,6 +10,9 @@ What's New in Python 3.2.1?
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #10979: unittest stdout buffering now works with class and module
setup and teardown.
- Issue #11510: Fixed optimizer bug which turned "a,b={1,1}" into "a,b=(1,1)". - Issue #11510: Fixed optimizer bug which turned "a,b={1,1}" into "a,b=(1,1)".
- Issue #11432: A bug was introduced in subprocess.Popen on posix systems with - Issue #11432: A bug was introduced in subprocess.Popen on posix systems with
......
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