114
114
Shows output in a different format, including displaying runtime for tests.
116
116
stop_early = False
118
def __init__(self, stream, descriptions, verbosity, pb=None):
119
unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
118
122
def _elapsedTime(self):
119
123
return "%5dms" % (1000 * (time.time() - self._start_time))
125
def _ellipsise_unimportant_words(self, a_string, final_width,
127
"""Add ellipsese (sp?) for overly long strings.
129
:param keep_start: If true preserve the start of a_string rather
133
if len(a_string) > final_width:
134
result = a_string[:final_width-3] + '...'
138
if len(a_string) > final_width:
139
result = '...' + a_string[3-final_width:]
142
return result.ljust(final_width)
121
144
def startTest(self, test):
122
145
unittest.TestResult.startTest(self, test)
123
146
# In a short description, the important words are in
124
147
# the beginning, but in an id, the important words are
126
149
SHOW_DESCRIPTIONS = False
151
if not self.showAll and self.dots and self.pb is not None:
154
final_width = osutils.terminal_width()
155
final_width = final_width - 15
157
if SHOW_DESCRIPTIONS:
158
what = test.shortDescription()
160
what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
163
if what.startswith('bzrlib.tests.'):
165
what = self._ellipsise_unimportant_words(what, final_width)
128
width = osutils.terminal_width()
129
name_width = width - 15
131
if SHOW_DESCRIPTIONS:
132
what = test.shortDescription()
134
if len(what) > name_width:
135
what = what[:name_width-3] + '...'
138
if what.startswith('bzrlib.tests.'):
140
if len(what) > name_width:
141
what = '...' + what[3-name_width:]
142
what = what.ljust(name_width)
143
167
self.stream.write(what)
168
elif self.dots and self.pb is not None:
169
self.pb.update(what, self.testsRun - 1, None)
144
170
self.stream.flush()
145
171
self._start_time = time.time()
150
176
unittest.TestResult.addError(self, test, err)
152
178
self.stream.writeln("ERROR %s" % self._elapsedTime())
179
elif self.dots and self.pb is None:
154
180
self.stream.write('E')
182
self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
155
183
self.stream.flush()
156
184
if self.stop_early:
160
188
unittest.TestResult.addFailure(self, test, err)
162
190
self.stream.writeln(" FAIL %s" % self._elapsedTime())
191
elif self.dots and self.pb is None:
164
192
self.stream.write('F')
194
self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
165
195
self.stream.flush()
166
196
if self.stop_early:
169
199
def addSuccess(self, test):
171
201
self.stream.writeln(' OK %s' % self._elapsedTime())
202
elif self.dots and self.pb is None:
173
203
self.stream.write('~')
205
self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
174
206
self.stream.flush()
175
207
unittest.TestResult.addSuccess(self, test)
179
211
print >>self.stream, ' SKIP %s' % self._elapsedTime()
180
212
print >>self.stream, ' %s' % skip_excinfo[1]
213
elif self.dots and self.pb is None:
182
214
self.stream.write('S')
216
self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
183
217
self.stream.flush()
184
218
# seems best to treat this as success from point-of-view of unittest
185
219
# -- it actually does nothing so it barely matters :)
200
234
self.stream.writeln("%s" % err)
203
class TextTestRunner(unittest.TextTestRunner):
237
class TextTestRunner(object):
204
238
stop_on_failure = False
246
self.stream = unittest._WritelnDecorator(stream)
247
self.descriptions = descriptions
248
self.verbosity = verbosity
249
self.keep_output = keep_output
206
252
def _makeResult(self):
207
result = _MyResult(self.stream, self.descriptions, self.verbosity)
253
result = _MyResult(self.stream,
208
257
result.stop_early = self.stop_on_failure
261
"Run the given test case or test suite."
262
result = self._makeResult()
263
startTime = time.time()
264
if self.pb is not None:
265
self.pb.update('Running tests', 0, test.countTestCases())
267
stopTime = time.time()
268
timeTaken = stopTime - startTime
270
self.stream.writeln(result.separator2)
271
run = result.testsRun
272
self.stream.writeln("Ran %d test%s in %.3fs" %
273
(run, run != 1 and "s" or "", timeTaken))
274
self.stream.writeln()
275
if not result.wasSuccessful():
276
self.stream.write("FAILED (")
277
failed, errored = map(len, (result.failures, result.errors))
279
self.stream.write("failures=%d" % failed)
281
if failed: self.stream.write(", ")
282
self.stream.write("errors=%d" % errored)
283
self.stream.writeln(")")
285
self.stream.writeln("OK")
286
if self.pb is not None:
287
self.pb.update('Cleaning up', 0, 1)
288
# This is still a little bogus,
289
# but only a little. Folk not using our testrunner will
290
# have to delete their temp directories themselves.
291
test_root = TestCaseInTempDir.TEST_ROOT
292
if result.wasSuccessful() or not self.keep_output:
293
if test_root is not None:
294
osutils.rmtree(test_root)
296
if self.pb is not None:
297
self.pb.note("Failed tests working directories are in '%s'\n",
301
"Failed tests working directories are in '%s'\n" %
303
TestCaseInTempDir.TEST_ROOT = None
304
if self.pb is not None:
212
309
def iter_suite_tests(suite):
213
310
"""Return all tests in a suite, recursing through nested suites"""
303
400
raise AssertionError('string %r does not start with %r' % (s, prefix))
305
402
def assertEndsWith(self, s, suffix):
306
if not s.endswith(prefix):
403
"""Asserts that s ends with suffix."""
404
if not s.endswith(suffix):
307
405
raise AssertionError('string %r does not end with %r' % (s, suffix))
309
407
def assertContainsRe(self, haystack, needle_re):
442
540
"""Shortcut that splits cmd into words, runs, and returns stdout"""
443
541
return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
445
def run_bzr_captured(self, argv, retcode=0):
543
def run_bzr_captured(self, argv, retcode=0, stdin=None):
446
544
"""Invoke bzr and return (stdout, stderr).
448
546
Useful for code that wants to check the contents of the
471
572
handler.setLevel(logging.INFO)
472
573
logger = logging.getLogger('')
473
574
logger.addHandler(handler)
575
old_ui_factory = bzrlib.ui.ui_factory
576
bzrlib.ui.ui_factory = bzrlib.tests.blackbox.TestUIFactory(
579
bzrlib.ui.ui_factory.stdin = stdin
475
result = self.apply_redirected(None, stdout, stderr,
581
result = self.apply_redirected(stdin, stdout, stderr,
476
582
bzrlib.commands.run_bzr_catch_errors,
479
585
logger.removeHandler(handler)
586
bzrlib.ui.ui_factory = old_ui_factory
480
587
out = stdout.getvalue()
481
588
err = stderr.getvalue()
497
604
This sends the stdout/stderr results into the test's log,
498
605
where it may be useful for debugging. See also run_captured.
607
:param stdin: A string to be used as stdin for the command.
500
609
retcode = kwargs.pop('retcode', 0)
501
return self.run_bzr_captured(args, retcode)
610
stdin = kwargs.pop('stdin', None)
611
return self.run_bzr_captured(args, retcode, stdin)
503
613
def check_inventory_shape(self, inv, shape):
504
614
"""Compare an inventory to a list of expected names.
890
1000
TestCaseInTempDir._TEST_NAME = name
1006
pb = progress.ProgressBar()
895
1007
runner = TextTestRunner(stream=sys.stdout,
1009
verbosity=verbosity,
1010
keep_output=keep_output,
898
1012
runner.stop_on_failure=stop_on_failure
899
1013
if pattern != '.*':
900
1014
suite = filter_suite_by_re(suite, pattern)
901
1015
result = runner.run(suite)
902
# This is still a little bogus,
903
# but only a little. Folk not using our testrunner will
904
# have to delete their temp directories themselves.
905
test_root = TestCaseInTempDir.TEST_ROOT
906
if result.wasSuccessful() or not keep_output:
907
if test_root is not None:
908
print 'Deleting test root %s...' % test_root
910
shutil.rmtree(test_root)
914
print "Failed tests working directories are in '%s'\n" % TestCaseInTempDir.TEST_ROOT
915
1016
return result.wasSuccessful()