157
158
class ExtendedTestResult(unittest._TextTestResult):
158
159
"""Accepts, reports and accumulates the results of running tests.
160
Compared to this unittest version this class adds support for profiling,
161
benchmarking, stopping as soon as a test fails, and skipping tests.
162
There are further-specialized subclasses for different types of display.
161
Compared to this unittest version this class adds support for
162
profiling, benchmarking, stopping as soon as a test fails, and
163
skipping tests. There are further-specialized subclasses for
164
different types of display.
166
When a test finishes, in whatever way, it calls one of the addSuccess,
167
addFailure or addError classes. These in turn may redirect to a more
168
specific case for the special test results supported by our extended
171
Note that just one of these objects is fed the results from many tests.
165
174
stop_early = False
200
209
self._overall_start_time = time.time()
202
def extractBenchmarkTime(self, testCase):
211
def _extractBenchmarkTime(self, testCase):
203
212
"""Add a benchmark time for the current test case."""
204
self._benchmarkTime = getattr(testCase, "_benchtime", None)
213
return getattr(testCase, "_benchtime", None)
206
215
def _elapsedTestTimeString(self):
207
216
"""Return a time string for the overall time the current test has taken."""
208
217
return self._formatTime(time.time() - self._start_time)
210
def _testTimeString(self):
211
if self._benchmarkTime is not None:
219
def _testTimeString(self, testCase):
220
benchmark_time = self._extractBenchmarkTime(testCase)
221
if benchmark_time is not None:
212
222
return "%s/%s" % (
213
self._formatTime(self._benchmarkTime),
223
self._formatTime(benchmark_time),
214
224
self._elapsedTestTimeString())
216
226
return " %s" % self._elapsedTestTimeString()
246
256
def addError(self, test, err):
247
self.extractBenchmarkTime(test)
248
self._cleanupLogFile(test)
257
"""Tell result that test finished with an error.
259
Called from the TestCase run() method when the test
260
fails with an unexpected error.
262
self._testConcluded(test)
249
263
if isinstance(err[1], TestSkipped):
250
return self.addSkipped(test, err)
264
return self._addSkipped(test, err)
251
265
elif isinstance(err[1], UnavailableFeature):
252
266
return self.addNotSupported(test, err[1].args[0])
253
unittest.TestResult.addError(self, test, err)
254
self.error_count += 1
255
self.report_error(test, err)
268
unittest.TestResult.addError(self, test, err)
269
self.error_count += 1
270
self.report_error(test, err)
259
274
def addFailure(self, test, err):
260
self._cleanupLogFile(test)
261
self.extractBenchmarkTime(test)
275
"""Tell result that test failed.
277
Called from the TestCase run() method when the test
278
fails because e.g. an assert() method failed.
280
self._testConcluded(test)
262
281
if isinstance(err[1], KnownFailure):
263
return self.addKnownFailure(test, err)
264
unittest.TestResult.addFailure(self, test, err)
265
self.failure_count += 1
266
self.report_failure(test, err)
270
def addKnownFailure(self, test, err):
282
return self._addKnownFailure(test, err)
284
unittest.TestResult.addFailure(self, test, err)
285
self.failure_count += 1
286
self.report_failure(test, err)
290
def addSuccess(self, test):
291
"""Tell result that test completed successfully.
293
Called from the TestCase run()
295
self._testConcluded(test)
296
if self._bench_history is not None:
297
benchmark_time = self._extractBenchmarkTime(test)
298
if benchmark_time is not None:
299
self._bench_history.write("%s %s\n" % (
300
self._formatTime(benchmark_time),
302
self.report_success(test)
303
unittest.TestResult.addSuccess(self, test)
305
def _testConcluded(self, test):
306
"""Common code when a test has finished.
308
Called regardless of whether it succeded, failed, etc.
310
self._cleanupLogFile(test)
312
def _addKnownFailure(self, test, err):
271
313
self.known_failure_count += 1
272
314
self.report_known_failure(test, err)
274
316
def addNotSupported(self, test, feature):
317
"""The test will not be run because of a missing feature.
319
# this can be called in two different ways: it may be that the
320
# test started running, and then raised (through addError)
321
# UnavailableFeature. Alternatively this method can be called
322
# while probing for features before running the tests; in that
323
# case we will see startTest and stopTest, but the test will never
275
325
self.unsupported.setdefault(str(feature), 0)
276
326
self.unsupported[str(feature)] += 1
277
327
self.report_unsupported(test, feature)
279
def addSuccess(self, test):
280
self.extractBenchmarkTime(test)
281
if self._bench_history is not None:
282
if self._benchmarkTime is not None:
283
self._bench_history.write("%s %s\n" % (
284
self._formatTime(self._benchmarkTime),
286
self.report_success(test)
287
unittest.TestResult.addSuccess(self, test)
289
def addSkipped(self, test, skip_excinfo):
329
def _addSkipped(self, test, skip_excinfo):
290
330
self.report_skip(test, skip_excinfo)
291
# seems best to treat this as success from point-of-view of unittest
292
# -- it actually does nothing so it barely matters :)
331
# seems best to treat this as success from point-of-view of
332
# unittest -- it actually does nothing so it barely matters :)
295
335
except KeyboardInterrupt:
458
498
def report_error(self, test, err):
459
499
self.stream.writeln('ERROR %s\n%s'
460
% (self._testTimeString(),
500
% (self._testTimeString(test),
461
501
self._error_summary(err)))
463
503
def report_failure(self, test, err):
464
504
self.stream.writeln(' FAIL %s\n%s'
465
% (self._testTimeString(),
505
% (self._testTimeString(test),
466
506
self._error_summary(err)))
468
508
def report_known_failure(self, test, err):
469
509
self.stream.writeln('XFAIL %s\n%s'
470
% (self._testTimeString(),
510
% (self._testTimeString(test),
471
511
self._error_summary(err)))
473
513
def report_success(self, test):
474
self.stream.writeln(' OK %s' % self._testTimeString())
514
self.stream.writeln(' OK %s' % self._testTimeString(test))
475
515
for bench_called, stats in getattr(test, '_benchcalls', []):
476
516
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
477
517
stats.pprint(file=self.stream)