61
67
from bzrlib.merge import merge_inner
62
68
import bzrlib.merge3
63
69
import bzrlib.osutils
64
import bzrlib.osutils as osutils
65
70
import bzrlib.plugin
66
import bzrlib.progress as progress
67
71
from bzrlib.revision import common_ancestor
68
72
import bzrlib.store
69
73
from bzrlib import symbol_versioning
70
74
import bzrlib.trace
71
75
from bzrlib.transport import get_transport
72
76
import bzrlib.transport
73
from bzrlib.transport.local import LocalRelpathServer
77
from bzrlib.transport.local import LocalURLServer
74
78
from bzrlib.transport.memory import MemoryServer
75
79
from bzrlib.transport.readonly import ReadonlyServer
76
from bzrlib.trace import mutter
80
from bzrlib.trace import mutter, note
77
81
from bzrlib.tests import TestUtil
78
82
from bzrlib.tests.TestUtil import (
82
86
from bzrlib.tests.treeshape import build_tree_contents
83
import bzrlib.urlutils as urlutils
84
87
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
86
default_transport = LocalRelpathServer
89
default_transport = LocalURLServer
88
91
MODULES_TO_TEST = []
89
92
MODULES_TO_DOCTEST = [
134
class _MyResult(unittest._TextTestResult):
135
"""Custom TestResult.
137
class ExtendedTestResult(unittest._TextTestResult):
138
"""Accepts, reports and accumulates the results of running tests.
137
Shows output in a different format, including displaying runtime for tests.
140
Compared to this unittest version this class adds support for profiling,
141
benchmarking, stopping as soon as a test fails, and skipping tests.
142
There are further-specialized subclasses for different types of display.
139
145
stop_early = False
141
def __init__(self, stream, descriptions, verbosity, pb=None,
147
def __init__(self, stream, descriptions, verbosity,
143
151
"""Construct new TestResult.
145
153
:param bench_history: Optionally, a writable file object to accumulate
146
154
benchmark results.
148
156
unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
150
157
if bench_history is not None:
151
158
from bzrlib.version import _get_bzr_source_tree
152
159
src_tree = _get_bzr_source_tree()
183
197
"""Format seconds as milliseconds with leading spaces."""
184
198
return "%5dms" % (1000 * seconds)
186
def _ellipsise_unimportant_words(self, a_string, final_width,
188
"""Add ellipses (sp?) for overly long strings.
190
:param keep_start: If true preserve the start of a_string rather
194
if len(a_string) > final_width:
195
result = a_string[:final_width-3] + '...'
199
if len(a_string) > final_width:
200
result = '...' + a_string[3-final_width:]
203
return result.ljust(final_width)
200
def _shortened_test_description(self, test):
202
what = re.sub(r'^bzrlib\.(tests|benchmark)\.', '', what)
205
205
def startTest(self, test):
206
206
unittest.TestResult.startTest(self, test)
207
# In a short description, the important words are in
208
# the beginning, but in an id, the important words are
210
SHOW_DESCRIPTIONS = False
212
if not self.showAll and self.dots and self.pb is not None:
215
final_width = osutils.terminal_width()
216
final_width = final_width - 15 - 8
218
if SHOW_DESCRIPTIONS:
219
what = test.shortDescription()
221
what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
224
if what.startswith('bzrlib.tests.'):
226
what = self._ellipsise_unimportant_words(what, final_width)
228
self.stream.write(what)
229
elif self.dots and self.pb is not None:
230
self.pb.update(what, self.testsRun - 1, None)
207
self.report_test_start(test)
232
208
self._recordTestStartTime()
234
210
def _recordTestStartTime(self):
286
244
self._bench_history.write("%s %s\n" % (
287
245
self._formatTime(self._benchmarkTime),
290
self.stream.writeln(' OK %s' % self._testTimeString())
291
for bench_called, stats in getattr(test, '_benchcalls', []):
292
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
293
stats.pprint(file=self.stream)
294
elif self.dots and self.pb is None:
295
self.stream.write('~')
297
self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
247
self.report_success(test)
299
248
unittest.TestResult.addSuccess(self, test)
301
250
def addSkipped(self, test, skip_excinfo):
302
251
self.extractBenchmarkTime(test)
304
print >>self.stream, ' SKIP %s' % self._testTimeString()
305
print >>self.stream, ' %s' % skip_excinfo[1]
306
elif self.dots and self.pb is None:
307
self.stream.write('S')
309
self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
252
self.report_skip(test, skip_excinfo)
311
253
# seems best to treat this as success from point-of-view of unittest
312
254
# -- it actually does nothing so it barely matters :)
333
275
self.stream.writeln(self.separator2)
334
276
self.stream.writeln("%s" % err)
281
def report_cleaning_up(self):
284
def report_success(self, test):
288
class TextTestResult(ExtendedTestResult):
289
"""Displays progress and results of tests in text form"""
291
def __init__(self, *args, **kw):
292
ExtendedTestResult.__init__(self, *args, **kw)
293
self.pb = self.ui.nested_progress_bar()
294
self.pb.show_pct = False
295
self.pb.show_spinner = False
296
self.pb.show_eta = False,
297
self.pb.show_count = False
298
self.pb.show_bar = False
300
def report_starting(self):
301
self.pb.update('[test 0/%d] starting...' % (self.num_tests))
303
def _progress_prefix_text(self):
304
a = '[%d' % self.count
305
if self.num_tests is not None:
306
a +='/%d' % self.num_tests
307
a += ' in %ds' % (time.time() - self._overall_start_time)
309
a += ', %d errors' % self.error_count
310
if self.failure_count:
311
a += ', %d failed' % self.failure_count
313
a += ', %d skipped' % self.skip_count
317
def report_test_start(self, test):
320
self._progress_prefix_text()
322
+ self._shortened_test_description(test))
324
def report_error(self, test, err):
325
self.error_count += 1
326
self.pb.note('ERROR: %s\n %s\n' % (
327
self._shortened_test_description(test),
331
def report_failure(self, test, err):
332
self.failure_count += 1
333
self.pb.note('FAIL: %s\n %s\n' % (
334
self._shortened_test_description(test),
338
def report_skip(self, test, skip_excinfo):
341
# at the moment these are mostly not things we can fix
342
# and so they just produce stipple; use the verbose reporter
345
# show test and reason for skip
346
self.pb.note('SKIP: %s\n %s\n' % (
347
self._shortened_test_description(test),
350
# since the class name was left behind in the still-visible
352
self.pb.note('SKIP: %s' % (skip_excinfo[1]))
354
def report_cleaning_up(self):
355
self.pb.update('cleaning up...')
361
class VerboseTestResult(ExtendedTestResult):
362
"""Produce long output, with one line per test run plus times"""
364
def _ellipsize_to_right(self, a_string, final_width):
365
"""Truncate and pad a string, keeping the right hand side"""
366
if len(a_string) > final_width:
367
result = '...' + a_string[3-final_width:]
370
return result.ljust(final_width)
372
def report_starting(self):
373
self.stream.write('running %d tests...\n' % self.num_tests)
375
def report_test_start(self, test):
377
name = self._shortened_test_description(test)
378
self.stream.write(self._ellipsize_to_right(name, 60))
381
def report_error(self, test, err):
382
self.error_count += 1
383
self.stream.writeln('ERROR %s\n %s'
384
% (self._testTimeString(), err[1]))
386
def report_failure(self, test, err):
387
self.failure_count += 1
388
self.stream.writeln('FAIL %s\n %s'
389
% (self._testTimeString(), err[1]))
391
def report_success(self, test):
392
self.stream.writeln(' OK %s' % self._testTimeString())
393
for bench_called, stats in getattr(test, '_benchcalls', []):
394
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
395
stats.pprint(file=self.stream)
398
def report_skip(self, test, skip_excinfo):
399
print >>self.stream, ' SKIP %s' % self._testTimeString()
400
print >>self.stream, ' %s' % skip_excinfo[1]
337
403
class TextTestRunner(object):
338
404
stop_on_failure = False
344
410
keep_output=False,
346
411
bench_history=None):
347
412
self.stream = unittest._WritelnDecorator(stream)
348
413
self.descriptions = descriptions
349
414
self.verbosity = verbosity
350
415
self.keep_output = keep_output
352
416
self._bench_history = bench_history
354
def _makeResult(self):
355
result = _MyResult(self.stream,
359
bench_history=self._bench_history)
360
result.stop_early = self.stop_on_failure
363
418
def run(self, test):
364
419
"Run the given test case or test suite."
365
result = self._makeResult()
366
420
startTime = time.time()
367
if self.pb is not None:
368
self.pb.update('Running tests', 0, test.countTestCases())
421
if self.verbosity == 1:
422
result_class = TextTestResult
423
elif self.verbosity >= 2:
424
result_class = VerboseTestResult
425
result = result_class(self.stream,
428
bench_history=self._bench_history,
429
num_tests=test.countTestCases(),
431
result.stop_early = self.stop_on_failure
432
result.report_starting()
370
434
stopTime = time.time()
371
435
timeTaken = stopTime - startTime