mirror of
https://github.com/python/cpython.git
synced 2025-11-03 15:11:34 +00:00
bpo-13236: Flush the output stream more often in unittest (GH-29864)
It can prevent some losses when output to buffered stream.
This commit is contained in:
parent
87a18deda4
commit
f42a06ba27
4 changed files with 54 additions and 5 deletions
|
|
@ -68,6 +68,7 @@ def _write_status(self, test, status):
|
||||||
self.stream.write(self.getDescription(test))
|
self.stream.write(self.getDescription(test))
|
||||||
self.stream.write(" ... ")
|
self.stream.write(" ... ")
|
||||||
self.stream.writeln(status)
|
self.stream.writeln(status)
|
||||||
|
self.stream.flush()
|
||||||
self._newline = True
|
self._newline = True
|
||||||
|
|
||||||
def addSubTest(self, test, subtest, err):
|
def addSubTest(self, test, subtest, err):
|
||||||
|
|
@ -121,6 +122,7 @@ def addExpectedFailure(self, test, err):
|
||||||
super(TextTestResult, self).addExpectedFailure(test, err)
|
super(TextTestResult, self).addExpectedFailure(test, err)
|
||||||
if self.showAll:
|
if self.showAll:
|
||||||
self.stream.writeln("expected failure")
|
self.stream.writeln("expected failure")
|
||||||
|
self.stream.flush()
|
||||||
elif self.dots:
|
elif self.dots:
|
||||||
self.stream.write("x")
|
self.stream.write("x")
|
||||||
self.stream.flush()
|
self.stream.flush()
|
||||||
|
|
@ -129,6 +131,7 @@ def addUnexpectedSuccess(self, test):
|
||||||
super(TextTestResult, self).addUnexpectedSuccess(test)
|
super(TextTestResult, self).addUnexpectedSuccess(test)
|
||||||
if self.showAll:
|
if self.showAll:
|
||||||
self.stream.writeln("unexpected success")
|
self.stream.writeln("unexpected success")
|
||||||
|
self.stream.flush()
|
||||||
elif self.dots:
|
elif self.dots:
|
||||||
self.stream.write("u")
|
self.stream.write("u")
|
||||||
self.stream.flush()
|
self.stream.flush()
|
||||||
|
|
@ -136,6 +139,7 @@ def addUnexpectedSuccess(self, test):
|
||||||
def printErrors(self):
|
def printErrors(self):
|
||||||
if self.dots or self.showAll:
|
if self.dots or self.showAll:
|
||||||
self.stream.writeln()
|
self.stream.writeln()
|
||||||
|
self.stream.flush()
|
||||||
self.printErrorList('ERROR', self.errors)
|
self.printErrorList('ERROR', self.errors)
|
||||||
self.printErrorList('FAIL', self.failures)
|
self.printErrorList('FAIL', self.failures)
|
||||||
|
|
||||||
|
|
@ -145,6 +149,7 @@ def printErrorList(self, flavour, errors):
|
||||||
self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
|
self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
|
||||||
self.stream.writeln(self.separator2)
|
self.stream.writeln(self.separator2)
|
||||||
self.stream.writeln("%s" % err)
|
self.stream.writeln("%s" % err)
|
||||||
|
self.stream.flush()
|
||||||
|
|
||||||
|
|
||||||
class TextTestRunner(object):
|
class TextTestRunner(object):
|
||||||
|
|
@ -239,4 +244,5 @@ def run(self, test):
|
||||||
self.stream.writeln(" (%s)" % (", ".join(infos),))
|
self.stream.writeln(" (%s)" % (", ".join(infos),))
|
||||||
else:
|
else:
|
||||||
self.stream.write("\n")
|
self.stream.write("\n")
|
||||||
|
self.stream.flush()
|
||||||
return result
|
return result
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
from test import support
|
from test import support
|
||||||
import unittest
|
import unittest
|
||||||
import unittest.test
|
import unittest.test
|
||||||
|
from .test_result import BufferedWriter
|
||||||
|
|
||||||
|
|
||||||
class Test_TestProgram(unittest.TestCase):
|
class Test_TestProgram(unittest.TestCase):
|
||||||
|
|
@ -104,30 +105,39 @@ def run(self, test):
|
||||||
program.testNames)
|
program.testNames)
|
||||||
|
|
||||||
def test_NonExit(self):
|
def test_NonExit(self):
|
||||||
|
stream = BufferedWriter()
|
||||||
program = unittest.main(exit=False,
|
program = unittest.main(exit=False,
|
||||||
argv=["foobar"],
|
argv=["foobar"],
|
||||||
testRunner=unittest.TextTestRunner(stream=io.StringIO()),
|
testRunner=unittest.TextTestRunner(stream=stream),
|
||||||
testLoader=self.FooBarLoader())
|
testLoader=self.FooBarLoader())
|
||||||
self.assertTrue(hasattr(program, 'result'))
|
self.assertTrue(hasattr(program, 'result'))
|
||||||
|
self.assertIn('\nFAIL: testFail ', stream.getvalue())
|
||||||
|
self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n'))
|
||||||
|
|
||||||
|
|
||||||
def test_Exit(self):
|
def test_Exit(self):
|
||||||
|
stream = BufferedWriter()
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
SystemExit,
|
SystemExit,
|
||||||
unittest.main,
|
unittest.main,
|
||||||
argv=["foobar"],
|
argv=["foobar"],
|
||||||
testRunner=unittest.TextTestRunner(stream=io.StringIO()),
|
testRunner=unittest.TextTestRunner(stream=stream),
|
||||||
exit=True,
|
exit=True,
|
||||||
testLoader=self.FooBarLoader())
|
testLoader=self.FooBarLoader())
|
||||||
|
self.assertIn('\nFAIL: testFail ', stream.getvalue())
|
||||||
|
self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n'))
|
||||||
|
|
||||||
|
|
||||||
def test_ExitAsDefault(self):
|
def test_ExitAsDefault(self):
|
||||||
|
stream = BufferedWriter()
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
SystemExit,
|
SystemExit,
|
||||||
unittest.main,
|
unittest.main,
|
||||||
argv=["foobar"],
|
argv=["foobar"],
|
||||||
testRunner=unittest.TextTestRunner(stream=io.StringIO()),
|
testRunner=unittest.TextTestRunner(stream=stream),
|
||||||
testLoader=self.FooBarLoader())
|
testLoader=self.FooBarLoader())
|
||||||
|
self.assertIn('\nFAIL: testFail ', stream.getvalue())
|
||||||
|
self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n'))
|
||||||
|
|
||||||
|
|
||||||
class InitialisableProgram(unittest.TestProgram):
|
class InitialisableProgram(unittest.TestProgram):
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,22 @@ def bad_cleanup2():
|
||||||
raise ValueError('bad cleanup2')
|
raise ValueError('bad cleanup2')
|
||||||
|
|
||||||
|
|
||||||
|
class BufferedWriter:
|
||||||
|
def __init__(self):
|
||||||
|
self.result = ''
|
||||||
|
self.buffer = ''
|
||||||
|
|
||||||
|
def write(self, arg):
|
||||||
|
self.buffer += arg
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
self.result += self.buffer
|
||||||
|
self.buffer = ''
|
||||||
|
|
||||||
|
def getvalue(self):
|
||||||
|
return self.result
|
||||||
|
|
||||||
|
|
||||||
class Test_TestResult(unittest.TestCase):
|
class Test_TestResult(unittest.TestCase):
|
||||||
# Note: there are not separate tests for TestResult.wasSuccessful(),
|
# Note: there are not separate tests for TestResult.wasSuccessful(),
|
||||||
# TestResult.errors, TestResult.failures, TestResult.testsRun or
|
# TestResult.errors, TestResult.failures, TestResult.testsRun or
|
||||||
|
|
@ -335,10 +351,13 @@ def testFailFast(self):
|
||||||
self.assertTrue(result.shouldStop)
|
self.assertTrue(result.shouldStop)
|
||||||
|
|
||||||
def testFailFastSetByRunner(self):
|
def testFailFastSetByRunner(self):
|
||||||
runner = unittest.TextTestRunner(stream=io.StringIO(), failfast=True)
|
stream = BufferedWriter()
|
||||||
|
runner = unittest.TextTestRunner(stream=stream, failfast=True)
|
||||||
def test(result):
|
def test(result):
|
||||||
self.assertTrue(result.failfast)
|
self.assertTrue(result.failfast)
|
||||||
result = runner.run(test)
|
result = runner.run(test)
|
||||||
|
stream.flush()
|
||||||
|
self.assertTrue(stream.getvalue().endswith('\n\nOK\n'))
|
||||||
|
|
||||||
|
|
||||||
class Test_TextTestResult(unittest.TestCase):
|
class Test_TextTestResult(unittest.TestCase):
|
||||||
|
|
@ -462,6 +481,12 @@ def testFail(self):
|
||||||
self.fail('fail')
|
self.fail('fail')
|
||||||
def testError(self):
|
def testError(self):
|
||||||
raise Exception('error')
|
raise Exception('error')
|
||||||
|
@unittest.expectedFailure
|
||||||
|
def testExpectedFailure(self):
|
||||||
|
self.fail('fail')
|
||||||
|
@unittest.expectedFailure
|
||||||
|
def testUnexpectedSuccess(self):
|
||||||
|
pass
|
||||||
def testSubTestSuccess(self):
|
def testSubTestSuccess(self):
|
||||||
with self.subTest('one', a=1):
|
with self.subTest('one', a=1):
|
||||||
pass
|
pass
|
||||||
|
|
@ -483,7 +508,7 @@ def tearDown(self):
|
||||||
raise self.tearDownError
|
raise self.tearDownError
|
||||||
|
|
||||||
def _run_test(self, test_name, verbosity, tearDownError=None):
|
def _run_test(self, test_name, verbosity, tearDownError=None):
|
||||||
stream = io.StringIO()
|
stream = BufferedWriter()
|
||||||
stream = unittest.runner._WritelnDecorator(stream)
|
stream = unittest.runner._WritelnDecorator(stream)
|
||||||
result = unittest.TextTestResult(stream, True, verbosity)
|
result = unittest.TextTestResult(stream, True, verbosity)
|
||||||
test = self.Test(test_name)
|
test = self.Test(test_name)
|
||||||
|
|
@ -496,6 +521,8 @@ def testDotsOutput(self):
|
||||||
self.assertEqual(self._run_test('testSkip', 1), 's')
|
self.assertEqual(self._run_test('testSkip', 1), 's')
|
||||||
self.assertEqual(self._run_test('testFail', 1), 'F')
|
self.assertEqual(self._run_test('testFail', 1), 'F')
|
||||||
self.assertEqual(self._run_test('testError', 1), 'E')
|
self.assertEqual(self._run_test('testError', 1), 'E')
|
||||||
|
self.assertEqual(self._run_test('testExpectedFailure', 1), 'x')
|
||||||
|
self.assertEqual(self._run_test('testUnexpectedSuccess', 1), 'u')
|
||||||
|
|
||||||
def testLongOutput(self):
|
def testLongOutput(self):
|
||||||
classname = f'{__name__}.{self.Test.__qualname__}'
|
classname = f'{__name__}.{self.Test.__qualname__}'
|
||||||
|
|
@ -507,6 +534,10 @@ def testLongOutput(self):
|
||||||
f'testFail ({classname}) ... FAIL\n')
|
f'testFail ({classname}) ... FAIL\n')
|
||||||
self.assertEqual(self._run_test('testError', 2),
|
self.assertEqual(self._run_test('testError', 2),
|
||||||
f'testError ({classname}) ... ERROR\n')
|
f'testError ({classname}) ... ERROR\n')
|
||||||
|
self.assertEqual(self._run_test('testExpectedFailure', 2),
|
||||||
|
f'testExpectedFailure ({classname}) ... expected failure\n')
|
||||||
|
self.assertEqual(self._run_test('testUnexpectedSuccess', 2),
|
||||||
|
f'testUnexpectedSuccess ({classname}) ... unexpected success\n')
|
||||||
|
|
||||||
def testDotsOutputSubTestSuccess(self):
|
def testDotsOutputSubTestSuccess(self):
|
||||||
self.assertEqual(self._run_test('testSubTestSuccess', 1), '.')
|
self.assertEqual(self._run_test('testSubTestSuccess', 1), '.')
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
:class:`unittest.TextTestResult` and :class:`unittest.TextTestRunner` flush
|
||||||
|
now the output stream more often.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue