blob: 8065642fdc5b499ac81bfd535e2060828d9578d3 [file] [log] [blame]
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001"""Running tests"""
2
3import sys
4import time
5
6from . import result
Michael Foord65b69a12010-03-27 13:25:41 +00007from .signals import registerResult
Benjamin Petersonbed7d042009-07-19 21:01:52 +00008
Benjamin Petersondccc1fc2010-03-22 00:15:53 +00009__unittest = True
10
Benjamin Petersonbed7d042009-07-19 21:01:52 +000011
12class _WritelnDecorator(object):
13 """Used to decorate file-like objects with a handy 'writeln' method"""
14 def __init__(self,stream):
15 self.stream = stream
16
17 def __getattr__(self, attr):
Antoine Pitrouc63ecee2009-11-10 21:34:48 +000018 if attr in ('stream', '__getstate__'):
19 raise AttributeError(attr)
Benjamin Petersonbed7d042009-07-19 21:01:52 +000020 return getattr(self.stream,attr)
21
22 def writeln(self, arg=None):
23 if arg:
24 self.write(arg)
25 self.write('\n') # text-mode streams translate to \r\n if needed
26
27
Michael Foord34c94622010-02-10 15:51:42 +000028class TextTestResult(result.TestResult):
Benjamin Petersonbed7d042009-07-19 21:01:52 +000029 """A test result class that can print formatted text results to a stream.
30
31 Used by TextTestRunner.
32 """
33 separator1 = '=' * 70
34 separator2 = '-' * 70
35
36 def __init__(self, stream, descriptions, verbosity):
Michael Foord34c94622010-02-10 15:51:42 +000037 super(TextTestResult, self).__init__()
Benjamin Petersonbed7d042009-07-19 21:01:52 +000038 self.stream = stream
39 self.showAll = verbosity > 1
40 self.dots = verbosity == 1
41 self.descriptions = descriptions
42
43 def getDescription(self, test):
Michael Foord34c94622010-02-10 15:51:42 +000044 doc_first_line = test.shortDescription()
45 if self.descriptions and doc_first_line:
46 return '\n'.join((str(test), doc_first_line))
Benjamin Petersonbed7d042009-07-19 21:01:52 +000047 else:
48 return str(test)
49
50 def startTest(self, test):
Michael Foord34c94622010-02-10 15:51:42 +000051 super(TextTestResult, self).startTest(test)
Benjamin Petersonbed7d042009-07-19 21:01:52 +000052 if self.showAll:
53 self.stream.write(self.getDescription(test))
54 self.stream.write(" ... ")
55 self.stream.flush()
56
57 def addSuccess(self, test):
Michael Foord34c94622010-02-10 15:51:42 +000058 super(TextTestResult, self).addSuccess(test)
Benjamin Petersonbed7d042009-07-19 21:01:52 +000059 if self.showAll:
60 self.stream.writeln("ok")
61 elif self.dots:
62 self.stream.write('.')
63 self.stream.flush()
64
65 def addError(self, test, err):
Michael Foord34c94622010-02-10 15:51:42 +000066 super(TextTestResult, self).addError(test, err)
Benjamin Petersonbed7d042009-07-19 21:01:52 +000067 if self.showAll:
68 self.stream.writeln("ERROR")
69 elif self.dots:
70 self.stream.write('E')
71 self.stream.flush()
72
73 def addFailure(self, test, err):
Michael Foord34c94622010-02-10 15:51:42 +000074 super(TextTestResult, self).addFailure(test, err)
Benjamin Petersonbed7d042009-07-19 21:01:52 +000075 if self.showAll:
76 self.stream.writeln("FAIL")
77 elif self.dots:
78 self.stream.write('F')
79 self.stream.flush()
80
81 def addSkip(self, test, reason):
Michael Foord34c94622010-02-10 15:51:42 +000082 super(TextTestResult, self).addSkip(test, reason)
Benjamin Petersonbed7d042009-07-19 21:01:52 +000083 if self.showAll:
84 self.stream.writeln("skipped {0!r}".format(reason))
85 elif self.dots:
86 self.stream.write("s")
87 self.stream.flush()
88
89 def addExpectedFailure(self, test, err):
Michael Foord34c94622010-02-10 15:51:42 +000090 super(TextTestResult, self).addExpectedFailure(test, err)
Benjamin Petersonbed7d042009-07-19 21:01:52 +000091 if self.showAll:
92 self.stream.writeln("expected failure")
93 elif self.dots:
94 self.stream.write("x")
95 self.stream.flush()
96
97 def addUnexpectedSuccess(self, test):
Michael Foord34c94622010-02-10 15:51:42 +000098 super(TextTestResult, self).addUnexpectedSuccess(test)
Benjamin Petersonbed7d042009-07-19 21:01:52 +000099 if self.showAll:
100 self.stream.writeln("unexpected success")
101 elif self.dots:
102 self.stream.write("u")
103 self.stream.flush()
104
105 def printErrors(self):
106 if self.dots or self.showAll:
107 self.stream.writeln()
108 self.printErrorList('ERROR', self.errors)
109 self.printErrorList('FAIL', self.failures)
110
111 def printErrorList(self, flavour, errors):
112 for test, err in errors:
113 self.stream.writeln(self.separator1)
114 self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
115 self.stream.writeln(self.separator2)
116 self.stream.writeln("%s" % err)
117
118
119class TextTestRunner(object):
120 """A test runner class that displays results in textual form.
121
122 It prints out the names of tests as they are run, errors as they
123 occur, and a summary of the results at the end of the test run.
124 """
Michael Foord34c94622010-02-10 15:51:42 +0000125 resultclass = TextTestResult
126
127 def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1,
Benjamin Peterson8769fd82010-03-22 01:13:48 +0000128 failfast=False, resultclass=None):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000129 self.stream = _WritelnDecorator(stream)
130 self.descriptions = descriptions
131 self.verbosity = verbosity
Benjamin Peterson8769fd82010-03-22 01:13:48 +0000132 self.failfast = failfast
Michael Foord34c94622010-02-10 15:51:42 +0000133 if resultclass is not None:
134 self.resultclass = resultclass
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000135
136 def _makeResult(self):
Michael Foord34c94622010-02-10 15:51:42 +0000137 return self.resultclass(self.stream, self.descriptions, self.verbosity)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000138
139 def run(self, test):
140 "Run the given test case or test suite."
141 result = self._makeResult()
Michael Foord65b69a12010-03-27 13:25:41 +0000142 registerResult(result)
Benjamin Peterson8769fd82010-03-22 01:13:48 +0000143 result.failfast = self.failfast
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000144 startTime = time.time()
145 startTestRun = getattr(result, 'startTestRun', None)
146 if startTestRun is not None:
147 startTestRun()
148 try:
149 test(result)
150 finally:
151 stopTestRun = getattr(result, 'stopTestRun', None)
152 if stopTestRun is not None:
153 stopTestRun()
154 stopTime = time.time()
155 timeTaken = stopTime - startTime
156 result.printErrors()
Benjamin Peterson847a4112010-03-14 15:04:17 +0000157 if hasattr(result, 'separator2'):
158 self.stream.writeln(result.separator2)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000159 run = result.testsRun
160 self.stream.writeln("Ran %d test%s in %.3fs" %
161 (run, run != 1 and "s" or "", timeTaken))
162 self.stream.writeln()
Benjamin Peterson847a4112010-03-14 15:04:17 +0000163
164 expectedFails = unexpectedSuccesses = skipped = 0
165 try:
166 results = map(len, (result.expectedFailures,
167 result.unexpectedSuccesses,
168 result.skipped))
169 expectedFails, unexpectedSuccesses, skipped = results
170 except AttributeError:
171 pass
172
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000173 infos = []
174 if not result.wasSuccessful():
175 self.stream.write("FAILED")
176 failed, errored = len(result.failures), len(result.errors)
177 if failed:
178 infos.append("failures=%d" % failed)
179 if errored:
180 infos.append("errors=%d" % errored)
181 else:
182 self.stream.write("OK")
183 if skipped:
184 infos.append("skipped=%d" % skipped)
185 if expectedFails:
186 infos.append("expected failures=%d" % expectedFails)
187 if unexpectedSuccesses:
188 infos.append("unexpected successes=%d" % unexpectedSuccesses)
189 if infos:
190 self.stream.writeln(" (%s)" % (", ".join(infos),))
191 else:
192 self.stream.write("\n")
193 return result