Skip to content

Commit d55a03e

Browse files
[3.10] bpo-13236: Flush the output stream more often in unittest (GH-29929) (GH-30039)
It can prevent some losses when output to buffered stream.. (cherry picked from commit 83fa129) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent 9299e3a commit d55a03e

File tree

4 files changed

+44
-4
lines changed

4 files changed

+44
-4
lines changed

Lib/unittest/runner.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ def addSuccess(self, test):
5959
super(TextTestResult, self).addSuccess(test)
6060
if self.showAll:
6161
self.stream.writeln("ok")
62+
self.stream.flush()
6263
elif self.dots:
6364
self.stream.write('.')
6465
self.stream.flush()
@@ -67,6 +68,7 @@ def addError(self, test, err):
6768
super(TextTestResult, self).addError(test, err)
6869
if self.showAll:
6970
self.stream.writeln("ERROR")
71+
self.stream.flush()
7072
elif self.dots:
7173
self.stream.write('E')
7274
self.stream.flush()
@@ -75,6 +77,7 @@ def addFailure(self, test, err):
7577
super(TextTestResult, self).addFailure(test, err)
7678
if self.showAll:
7779
self.stream.writeln("FAIL")
80+
self.stream.flush()
7881
elif self.dots:
7982
self.stream.write('F')
8083
self.stream.flush()
@@ -83,6 +86,7 @@ def addSkip(self, test, reason):
8386
super(TextTestResult, self).addSkip(test, reason)
8487
if self.showAll:
8588
self.stream.writeln("skipped {0!r}".format(reason))
89+
self.stream.flush()
8690
elif self.dots:
8791
self.stream.write("s")
8892
self.stream.flush()
@@ -91,6 +95,7 @@ def addExpectedFailure(self, test, err):
9195
super(TextTestResult, self).addExpectedFailure(test, err)
9296
if self.showAll:
9397
self.stream.writeln("expected failure")
98+
self.stream.flush()
9499
elif self.dots:
95100
self.stream.write("x")
96101
self.stream.flush()
@@ -99,13 +104,15 @@ def addUnexpectedSuccess(self, test):
99104
super(TextTestResult, self).addUnexpectedSuccess(test)
100105
if self.showAll:
101106
self.stream.writeln("unexpected success")
107+
self.stream.flush()
102108
elif self.dots:
103109
self.stream.write("u")
104110
self.stream.flush()
105111

106112
def printErrors(self):
107113
if self.dots or self.showAll:
108114
self.stream.writeln()
115+
self.stream.flush()
109116
self.printErrorList('ERROR', self.errors)
110117
self.printErrorList('FAIL', self.failures)
111118

@@ -115,6 +122,7 @@ def printErrorList(self, flavour, errors):
115122
self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
116123
self.stream.writeln(self.separator2)
117124
self.stream.writeln("%s" % err)
125+
self.stream.flush()
118126

119127

120128
class TextTestRunner(object):
@@ -218,4 +226,5 @@ def run(self, test):
218226
self.stream.writeln(" (%s)" % (", ".join(infos),))
219227
else:
220228
self.stream.write("\n")
229+
self.stream.flush()
221230
return result

Lib/unittest/test/test_program.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from test import support
77
import unittest
88
import unittest.test
9+
from .test_result import BufferedWriter
910

1011

1112
class Test_TestProgram(unittest.TestCase):
@@ -104,30 +105,39 @@ def run(self, test):
104105
program.testNames)
105106

106107
def test_NonExit(self):
108+
stream = BufferedWriter()
107109
program = unittest.main(exit=False,
108110
argv=["foobar"],
109-
testRunner=unittest.TextTestRunner(stream=io.StringIO()),
111+
testRunner=unittest.TextTestRunner(stream=stream),
110112
testLoader=self.FooBarLoader())
111113
self.assertTrue(hasattr(program, 'result'))
114+
self.assertIn('\nFAIL: testFail ', stream.getvalue())
115+
self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n'))
112116

113117

114118
def test_Exit(self):
119+
stream = BufferedWriter()
115120
self.assertRaises(
116121
SystemExit,
117122
unittest.main,
118123
argv=["foobar"],
119-
testRunner=unittest.TextTestRunner(stream=io.StringIO()),
124+
testRunner=unittest.TextTestRunner(stream=stream),
120125
exit=True,
121126
testLoader=self.FooBarLoader())
127+
self.assertIn('\nFAIL: testFail ', stream.getvalue())
128+
self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n'))
122129

123130

124131
def test_ExitAsDefault(self):
132+
stream = BufferedWriter()
125133
self.assertRaises(
126134
SystemExit,
127135
unittest.main,
128136
argv=["foobar"],
129-
testRunner=unittest.TextTestRunner(stream=io.StringIO()),
137+
testRunner=unittest.TextTestRunner(stream=stream),
130138
testLoader=self.FooBarLoader())
139+
self.assertIn('\nFAIL: testFail ', stream.getvalue())
140+
self.assertTrue(stream.getvalue().endswith('\n\nFAILED (failures=1)\n'))
131141

132142

133143
class InitialisableProgram(unittest.TestProgram):

Lib/unittest/test/test_result.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,22 @@ def bad_cleanup2():
3434
raise ValueError('bad cleanup2')
3535

3636

37+
class BufferedWriter:
38+
def __init__(self):
39+
self.result = ''
40+
self.buffer = ''
41+
42+
def write(self, arg):
43+
self.buffer += arg
44+
45+
def flush(self):
46+
self.result += self.buffer
47+
self.buffer = ''
48+
49+
def getvalue(self):
50+
return self.result
51+
52+
3753
class Test_TestResult(unittest.TestCase):
3854
# Note: there are not separate tests for TestResult.wasSuccessful(),
3955
# TestResult.errors, TestResult.failures, TestResult.testsRun or
@@ -445,10 +461,13 @@ def testFailFast(self):
445461
self.assertTrue(result.shouldStop)
446462

447463
def testFailFastSetByRunner(self):
448-
runner = unittest.TextTestRunner(stream=io.StringIO(), failfast=True)
464+
stream = BufferedWriter()
465+
runner = unittest.TextTestRunner(stream=stream, failfast=True)
449466
def test(result):
450467
self.assertTrue(result.failfast)
451468
result = runner.run(test)
469+
stream.flush()
470+
self.assertTrue(stream.getvalue().endswith('\n\nOK\n'))
452471

453472

454473
classDict = dict(unittest.TestResult.__dict__)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:class:`unittest.TextTestResult` and :class:`unittest.TextTestRunner` flush
2+
now the output stream more often.

0 commit comments

Comments
 (0)