114
124
Shows output in a different format, including displaying runtime for tests.
116
126
stop_early = False
118
def _elapsedTime(self):
119
return "%5dms" % (1000 * (time.time() - self._start_time))
128
def __init__(self, stream, descriptions, verbosity, pb=None):
129
unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
132
def extractBenchmarkTime(self, testCase):
133
"""Add a benchmark time for the current test case."""
134
self._benchmarkTime = getattr(testCase, "_benchtime", None)
136
def _elapsedTestTimeString(self):
137
"""Return a time string for the overall time the current test has taken."""
138
return self._formatTime(time.time() - self._start_time)
140
def _testTimeString(self):
141
if self._benchmarkTime is not None:
143
self._formatTime(self._benchmarkTime),
144
self._elapsedTestTimeString())
146
return " %s" % self._elapsedTestTimeString()
148
def _formatTime(self, seconds):
149
"""Format seconds as milliseconds with leading spaces."""
150
return "%5dms" % (1000 * seconds)
152
def _ellipsise_unimportant_words(self, a_string, final_width,
154
"""Add ellipses (sp?) for overly long strings.
156
:param keep_start: If true preserve the start of a_string rather
160
if len(a_string) > final_width:
161
result = a_string[:final_width-3] + '...'
165
if len(a_string) > final_width:
166
result = '...' + a_string[3-final_width:]
169
return result.ljust(final_width)
121
171
def startTest(self, test):
122
172
unittest.TestResult.startTest(self, test)
124
174
# the beginning, but in an id, the important words are
126
176
SHOW_DESCRIPTIONS = False
178
if not self.showAll and self.dots and self.pb is not None:
181
final_width = osutils.terminal_width()
182
final_width = final_width - 15 - 8
184
if SHOW_DESCRIPTIONS:
185
what = test.shortDescription()
187
what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
190
if what.startswith('bzrlib.tests.'):
192
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
194
self.stream.write(what)
195
elif self.dots and self.pb is not None:
196
self.pb.update(what, self.testsRun - 1, None)
144
197
self.stream.flush()
198
self._recordTestStartTime()
200
def _recordTestStartTime(self):
201
"""Record that a test has started."""
145
202
self._start_time = time.time()
147
204
def addError(self, test, err):
148
205
if isinstance(err[1], TestSkipped):
149
206
return self.addSkipped(test, err)
150
207
unittest.TestResult.addError(self, test, err)
208
self.extractBenchmarkTime(test)
152
self.stream.writeln("ERROR %s" % self._elapsedTime())
210
self.stream.writeln("ERROR %s" % self._testTimeString())
211
elif self.dots and self.pb is None:
154
212
self.stream.write('E')
214
self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
155
215
self.stream.flush()
156
216
if self.stop_early:
159
219
def addFailure(self, test, err):
160
220
unittest.TestResult.addFailure(self, test, err)
221
self.extractBenchmarkTime(test)
162
self.stream.writeln(" FAIL %s" % self._elapsedTime())
223
self.stream.writeln(" FAIL %s" % self._testTimeString())
224
elif self.dots and self.pb is None:
164
225
self.stream.write('F')
227
self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
165
228
self.stream.flush()
166
229
if self.stop_early:
169
232
def addSuccess(self, test):
233
self.extractBenchmarkTime(test)
171
self.stream.writeln(' OK %s' % self._elapsedTime())
235
self.stream.writeln(' OK %s' % self._testTimeString())
236
for bench_called, stats in getattr(test, '_benchcalls', []):
237
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
238
stats.pprint(file=self.stream)
239
elif self.dots and self.pb is None:
173
240
self.stream.write('~')
242
self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
174
243
self.stream.flush()
175
244
unittest.TestResult.addSuccess(self, test)
177
246
def addSkipped(self, test, skip_excinfo):
247
self.extractBenchmarkTime(test)
179
print >>self.stream, ' SKIP %s' % self._elapsedTime()
249
print >>self.stream, ' SKIP %s' % self._testTimeString()
180
250
print >>self.stream, ' %s' % skip_excinfo[1]
251
elif self.dots and self.pb is None:
182
252
self.stream.write('S')
254
self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
183
255
self.stream.flush()
184
256
# seems best to treat this as success from point-of-view of unittest
185
257
# -- it actually does nothing so it barely matters :)
200
272
self.stream.writeln("%s" % err)
203
class TextTestRunner(unittest.TextTestRunner):
275
class TextTestRunner(object):
204
276
stop_on_failure = False
284
self.stream = unittest._WritelnDecorator(stream)
285
self.descriptions = descriptions
286
self.verbosity = verbosity
287
self.keep_output = keep_output
206
290
def _makeResult(self):
207
result = _MyResult(self.stream, self.descriptions, self.verbosity)
291
result = _MyResult(self.stream,
208
295
result.stop_early = self.stop_on_failure
299
"Run the given test case or test suite."
300
result = self._makeResult()
301
startTime = time.time()
302
if self.pb is not None:
303
self.pb.update('Running tests', 0, test.countTestCases())
305
stopTime = time.time()
306
timeTaken = stopTime - startTime
308
self.stream.writeln(result.separator2)
309
run = result.testsRun
310
self.stream.writeln("Ran %d test%s in %.3fs" %
311
(run, run != 1 and "s" or "", timeTaken))
312
self.stream.writeln()
313
if not result.wasSuccessful():
314
self.stream.write("FAILED (")
315
failed, errored = map(len, (result.failures, result.errors))
317
self.stream.write("failures=%d" % failed)
319
if failed: self.stream.write(", ")
320
self.stream.write("errors=%d" % errored)
321
self.stream.writeln(")")
323
self.stream.writeln("OK")
324
if self.pb is not None:
325
self.pb.update('Cleaning up', 0, 1)
326
# This is still a little bogus,
327
# but only a little. Folk not using our testrunner will
328
# have to delete their temp directories themselves.
329
test_root = TestCaseInTempDir.TEST_ROOT
330
if result.wasSuccessful() or not self.keep_output:
331
if test_root is not None:
332
osutils.rmtree(test_root)
334
if self.pb is not None:
335
self.pb.note("Failed tests working directories are in '%s'\n",
339
"Failed tests working directories are in '%s'\n" %
341
TestCaseInTempDir.TEST_ROOT = None
342
if self.pb is not None:
212
347
def iter_suite_tests(suite):
213
348
"""Return all tests in a suite, recursing through nested suites"""
445
583
self._runCleanups()
446
584
unittest.TestCase.tearDown(self)
586
def time(self, callable, *args, **kwargs):
587
"""Run callable and accrue the time it takes to the benchmark time.
589
If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
590
this will cause lsprofile statistics to be gathered and stored in
593
if self._benchtime is None:
597
if not self._gather_lsprof_in_benchmarks:
598
return callable(*args, **kwargs)
600
# record this benchmark
601
ret, stats = bzrlib.lsprof.profile(callable, *args, **kwargs)
603
self._benchcalls.append(((callable, args, kwargs), stats))
606
self._benchtime += time.time() - start
448
608
def _runCleanups(self):
449
609
"""Run registered cleanup functions.
944
1104
def run_suite(suite, name='test', verbose=False, pattern=".*",
945
1105
stop_on_failure=False, keep_output=False,
1106
transport=None, lsprof_timed=None):
947
1107
TestCaseInTempDir._TEST_NAME = name
1108
TestCase._gather_lsprof_in_benchmarks = lsprof_timed
1114
pb = progress.ProgressBar()
952
1115
runner = TextTestRunner(stream=sys.stdout,
1117
verbosity=verbosity,
1118
keep_output=keep_output,
955
1120
runner.stop_on_failure=stop_on_failure
956
1121
if pattern != '.*':
957
1122
suite = filter_suite_by_re(suite, pattern)
958
1123
result = runner.run(suite)
959
# This is still a little bogus,
960
# but only a little. Folk not using our testrunner will
961
# have to delete their temp directories themselves.
962
test_root = TestCaseInTempDir.TEST_ROOT
963
if result.wasSuccessful() or not keep_output:
964
if test_root is not None:
965
print 'Deleting test root %s...' % test_root
967
osutils.rmtree(test_root)
971
print "Failed tests working directories are in '%s'\n" % TestCaseInTempDir.TEST_ROOT
972
1124
return result.wasSuccessful()
975
1127
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
976
1128
keep_output=False,
1130
test_suite_factory=None,
978
1132
"""Run the whole test suite under the enhanced runner"""
979
1133
global default_transport
980
1134
if transport is None:
981
1135
transport = default_transport
982
1136
old_transport = default_transport
983
1137
default_transport = transport
1139
if test_suite_factory is None:
1140
suite = test_suite()
1142
suite = test_suite_factory()
986
1143
return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
987
1144
stop_on_failure=stop_on_failure, keep_output=keep_output,
1145
transport=transport,
1146
lsprof_timed=lsprof_timed)
990
1148
default_transport = old_transport
994
1151
def test_suite():
995
"""Build and return TestSuite for the whole program."""
1152
"""Build and return TestSuite for the whole of bzrlib.
1154
This function can be replaced if you need to change the default test
1155
suite on a global basis, but it is not encouraged.
996
1157
from doctest import DocTestSuite
998
1159
global MODULES_TO_DOCTEST
1071
1235
test_transport_implementations = [
1072
1236
'bzrlib.tests.test_transport_implementations']
1074
TestCase.BZRPATH = osutils.pathjoin(
1075
osutils.realpath(osutils.dirname(bzrlib.__path__[0])), 'bzr')
1076
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1077
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1079
1238
suite = TestSuite()
1080
# python2.4's TestLoader.loadTestsFromNames gives very poor
1081
# errors if it fails to load a named module - no indication of what's
1082
# actually wrong, just "no such module". We should probably override that
1083
# class, but for the moment just load them ourselves. (mbp 20051202)
1084
loader = TestLoader()
1239
loader = TestUtil.TestLoader()
1085
1240
from bzrlib.transport import TransportTestProviderAdapter
1086
1241
adapter = TransportTestProviderAdapter()
1087
1242
adapt_modules(test_transport_implementations, adapter, loader, suite)
1088
for mod_name in testmod_names:
1089
mod = _load_module_by_name(mod_name)
1090
suite.addTest(loader.loadTestsFromModule(mod))
1243
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1091
1244
for package in packages_to_test():
1092
1245
suite.addTest(package.test_suite())
1093
1246
for m in MODULES_TO_TEST:
1103
1256
def adapt_modules(mods_list, adapter, loader, suite):
1104
1257
"""Adapt the modules in mods_list using adapter and add to suite."""
1105
for mod_name in mods_list:
1106
mod = _load_module_by_name(mod_name)
1107
for test in iter_suite_tests(loader.loadTestsFromModule(mod)):
1108
suite.addTests(adapter.adapt(test))
1111
def _load_module_by_name(mod_name):
1112
parts = mod_name.split('.')
1113
module = __import__(mod_name)
1115
# for historical reasons python returns the top-level module even though
1116
# it loads the submodule; we need to walk down to get the one we want.
1118
module = getattr(module, parts.pop(0))
1258
for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
1259
suite.addTests(adapter.adapt(test))