This should finally fix #6896. Let's watch the buildbots.
[python.git] / Lib / unittest / runner.py
blob67839f580e6daca4e3dd0be813af8390d37246ae
1 """Running tests"""
3 import sys
4 import time
6 from . import result
9 class _WritelnDecorator(object):
10 """Used to decorate file-like objects with a handy 'writeln' method"""
11 def __init__(self,stream):
12 self.stream = stream
14 def __getattr__(self, attr):
15 return getattr(self.stream,attr)
17 def writeln(self, arg=None):
18 if arg:
19 self.write(arg)
20 self.write('\n') # text-mode streams translate to \r\n if needed
23 class _TextTestResult(result.TestResult):
24 """A test result class that can print formatted text results to a stream.
26 Used by TextTestRunner.
27 """
28 separator1 = '=' * 70
29 separator2 = '-' * 70
31 def __init__(self, stream, descriptions, verbosity):
32 super(_TextTestResult, self).__init__()
33 self.stream = stream
34 self.showAll = verbosity > 1
35 self.dots = verbosity == 1
36 self.descriptions = descriptions
38 def getDescription(self, test):
39 if self.descriptions:
40 return test.shortDescription() or str(test)
41 else:
42 return str(test)
44 def startTest(self, test):
45 super(_TextTestResult, self).startTest(test)
46 if self.showAll:
47 self.stream.write(self.getDescription(test))
48 self.stream.write(" ... ")
49 self.stream.flush()
51 def addSuccess(self, test):
52 super(_TextTestResult, self).addSuccess(test)
53 if self.showAll:
54 self.stream.writeln("ok")
55 elif self.dots:
56 self.stream.write('.')
57 self.stream.flush()
59 def addError(self, test, err):
60 super(_TextTestResult, self).addError(test, err)
61 if self.showAll:
62 self.stream.writeln("ERROR")
63 elif self.dots:
64 self.stream.write('E')
65 self.stream.flush()
67 def addFailure(self, test, err):
68 super(_TextTestResult, self).addFailure(test, err)
69 if self.showAll:
70 self.stream.writeln("FAIL")
71 elif self.dots:
72 self.stream.write('F')
73 self.stream.flush()
75 def addSkip(self, test, reason):
76 super(_TextTestResult, self).addSkip(test, reason)
77 if self.showAll:
78 self.stream.writeln("skipped {0!r}".format(reason))
79 elif self.dots:
80 self.stream.write("s")
81 self.stream.flush()
83 def addExpectedFailure(self, test, err):
84 super(_TextTestResult, self).addExpectedFailure(test, err)
85 if self.showAll:
86 self.stream.writeln("expected failure")
87 elif self.dots:
88 self.stream.write("x")
89 self.stream.flush()
91 def addUnexpectedSuccess(self, test):
92 super(_TextTestResult, self).addUnexpectedSuccess(test)
93 if self.showAll:
94 self.stream.writeln("unexpected success")
95 elif self.dots:
96 self.stream.write("u")
97 self.stream.flush()
99 def printErrors(self):
100 if self.dots or self.showAll:
101 self.stream.writeln()
102 self.printErrorList('ERROR', self.errors)
103 self.printErrorList('FAIL', self.failures)
105 def printErrorList(self, flavour, errors):
106 for test, err in errors:
107 self.stream.writeln(self.separator1)
108 self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
109 self.stream.writeln(self.separator2)
110 self.stream.writeln("%s" % err)
113 class TextTestRunner(object):
114 """A test runner class that displays results in textual form.
116 It prints out the names of tests as they are run, errors as they
117 occur, and a summary of the results at the end of the test run.
119 def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1):
120 self.stream = _WritelnDecorator(stream)
121 self.descriptions = descriptions
122 self.verbosity = verbosity
124 def _makeResult(self):
125 return _TextTestResult(self.stream, self.descriptions, self.verbosity)
127 def run(self, test):
128 "Run the given test case or test suite."
129 result = self._makeResult()
130 startTime = time.time()
131 startTestRun = getattr(result, 'startTestRun', None)
132 if startTestRun is not None:
133 startTestRun()
134 try:
135 test(result)
136 finally:
137 stopTestRun = getattr(result, 'stopTestRun', None)
138 if stopTestRun is not None:
139 stopTestRun()
140 stopTime = time.time()
141 timeTaken = stopTime - startTime
142 result.printErrors()
143 self.stream.writeln(result.separator2)
144 run = result.testsRun
145 self.stream.writeln("Ran %d test%s in %.3fs" %
146 (run, run != 1 and "s" or "", timeTaken))
147 self.stream.writeln()
148 results = map(len, (result.expectedFailures,
149 result.unexpectedSuccesses,
150 result.skipped))
151 expectedFails, unexpectedSuccesses, skipped = results
152 infos = []
153 if not result.wasSuccessful():
154 self.stream.write("FAILED")
155 failed, errored = map(len, (result.failures, result.errors))
156 if failed:
157 infos.append("failures=%d" % failed)
158 if errored:
159 infos.append("errors=%d" % errored)
160 else:
161 self.stream.write("OK")
162 if skipped:
163 infos.append("skipped=%d" % skipped)
164 if expectedFails:
165 infos.append("expected failures=%d" % expectedFails)
166 if unexpectedSuccesses:
167 infos.append("unexpected successes=%d" % unexpectedSuccesses)
168 if infos:
169 self.stream.writeln(" (%s)" % (", ".join(infos),))
170 else:
171 self.stream.write("\n")
172 return result