Closes issue 10979. unittest buffering now works with class and module setup and teardown
This commit is contained in:
commit
e9ff2ef204
|
@ -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):
|
||||||
|
|
||||||
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):
|
||||||
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
|
||||||
__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):
|
||||||
|
|
||||||
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):
|
||||||
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):
|
||||||
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):
|
||||||
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):
|
||||||
|
|
||||||
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):
|
||||||
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):
|
||||||
|
|
||||||
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):
|
||||||
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):
|
||||||
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()
|
||||||
|
|
|
@ -72,6 +72,10 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
|
||||||
|
- Issue #10979: unittest stdout buffering now works with class and module
|
||||||
|
setup and teardown.
|
||||||
|
|
||||||
- Issue #11577: fix ResourceWarning triggered by improved binhex test coverage
|
- Issue #11577: fix ResourceWarning triggered by improved binhex test coverage
|
||||||
|
|
||||||
- Issue #11243: fix the parameter querying methods of Message to work if
|
- Issue #11243: fix the parameter querying methods of Message to work if
|
||||||
|
|
Loading…
Reference in New Issue