blob: f13d623f764db501c20aeb50a2bba65d2e1cf90b [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 Petersonb48af542010-04-11 20:43:16 +0000128 failfast=False, buffer=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
Benjamin Petersonb48af542010-04-11 20:43:16 +0000133 self.buffer = buffer
Michael Foord34c94622010-02-10 15:51:42 +0000134 if resultclass is not None:
135 self.resultclass = resultclass
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000136
137 def _makeResult(self):
Michael Foord34c94622010-02-10 15:51:42 +0000138 return self.resultclass(self.stream, self.descriptions, self.verbosity)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000139
140 def run(self, test):
141 "Run the given test case or test suite."
142 result = self._makeResult()
Michael Foord65b69a12010-03-27 13:25:41 +0000143 registerResult(result)
Benjamin Peterson8769fd82010-03-22 01:13:48 +0000144 result.failfast = self.failfast
Benjamin Petersonb48af542010-04-11 20:43:16 +0000145 result.buffer = self.buffer
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000146 startTime = time.time()
147 startTestRun = getattr(result, 'startTestRun', None)
148 if startTestRun is not None:
149 startTestRun()
150 try:
151 test(result)
152 finally:
153 stopTestRun = getattr(result, 'stopTestRun', None)
154 if stopTestRun is not None:
155 stopTestRun()
156 stopTime = time.time()
157 timeTaken = stopTime - startTime
158 result.printErrors()
Benjamin Peterson847a4112010-03-14 15:04:17 +0000159 if hasattr(result, 'separator2'):
160 self.stream.writeln(result.separator2)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000161 run = result.testsRun
162 self.stream.writeln("Ran %d test%s in %.3fs" %
163 (run, run != 1 and "s" or "", timeTaken))
164 self.stream.writeln()
Benjamin Peterson847a4112010-03-14 15:04:17 +0000165
166 expectedFails = unexpectedSuccesses = skipped = 0
167 try:
168 results = map(len, (result.expectedFailures,
169 result.unexpectedSuccesses,
170 result.skipped))
171 expectedFails, unexpectedSuccesses, skipped = results
172 except AttributeError:
173 pass
174
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000175 infos = []
176 if not result.wasSuccessful():
177 self.stream.write("FAILED")
178 failed, errored = len(result.failures), len(result.errors)
179 if failed:
180 infos.append("failures=%d" % failed)
181 if errored:
182 infos.append("errors=%d" % errored)
183 else:
184 self.stream.write("OK")
185 if skipped:
186 infos.append("skipped=%d" % skipped)
187 if expectedFails:
188 infos.append("expected failures=%d" % expectedFails)
189 if unexpectedSuccesses:
190 infos.append("unexpected successes=%d" % unexpectedSuccesses)
191 if infos:
192 self.stream.writeln(" (%s)" % (", ".join(infos),))
193 else:
194 self.stream.write("\n")
195 return result