114
112
Shows output in a different format, including displaying runtime for tests.
116
114
stop_early = False
118
def __init__(self, stream, descriptions, verbosity, pb=None):
119
unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
122
def extractBenchmarkTime(self, testCase):
123
"""Add a benchmark time for the current test case."""
124
self._benchmarkTime = getattr(testCase, "_benchtime", None)
126
def _elapsedTestTimeString(self):
127
"""Return a time string for the overall time the current test has taken."""
128
return self._formatTime(time.time() - self._start_time)
130
def _testTimeString(self):
131
if self._benchmarkTime is not None:
133
self._formatTime(self._benchmarkTime),
134
self._elapsedTestTimeString())
136
return " %s" % self._elapsedTestTimeString()
138
def _formatTime(self, seconds):
139
"""Format seconds as milliseconds with leading spaces."""
140
return "%5dms" % (1000 * seconds)
142
def _ellipsise_unimportant_words(self, a_string, final_width,
144
"""Add ellipses (sp?) for overly long strings.
146
:param keep_start: If true preserve the start of a_string rather
150
if len(a_string) > final_width:
151
result = a_string[:final_width-3] + '...'
155
if len(a_string) > final_width:
156
result = '...' + a_string[3-final_width:]
159
return result.ljust(final_width)
116
def _elapsedTime(self):
117
return "%5dms" % (1000 * (time.time() - self._start_time))
161
119
def startTest(self, test):
162
120
unittest.TestResult.startTest(self, test)
164
122
# the beginning, but in an id, the important words are
166
124
SHOW_DESCRIPTIONS = False
168
if not self.showAll and self.dots and self.pb is not None:
171
final_width = osutils.terminal_width()
172
final_width = final_width - 15 - 8
174
if SHOW_DESCRIPTIONS:
175
what = test.shortDescription()
177
what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
180
if what.startswith('bzrlib.tests.'):
182
what = self._ellipsise_unimportant_words(what, final_width)
126
width = osutils.terminal_width()
127
name_width = width - 15
129
if SHOW_DESCRIPTIONS:
130
what = test.shortDescription()
132
if len(what) > name_width:
133
what = what[:name_width-3] + '...'
136
if what.startswith('bzrlib.tests.'):
138
if len(what) > name_width:
139
what = '...' + what[3-name_width:]
140
what = what.ljust(name_width)
184
141
self.stream.write(what)
185
elif self.dots and self.pb is not None:
186
self.pb.update(what, self.testsRun - 1, None)
187
142
self.stream.flush()
188
self._recordTestStartTime()
190
def _recordTestStartTime(self):
191
"""Record that a test has started."""
192
143
self._start_time = time.time()
194
145
def addError(self, test, err):
195
146
if isinstance(err[1], TestSkipped):
196
147
return self.addSkipped(test, err)
197
148
unittest.TestResult.addError(self, test, err)
198
self.extractBenchmarkTime(test)
200
self.stream.writeln("ERROR %s" % self._testTimeString())
201
elif self.dots and self.pb is None:
150
self.stream.writeln("ERROR %s" % self._elapsedTime())
202
152
self.stream.write('E')
204
self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
205
153
self.stream.flush()
206
154
if self.stop_early:
209
157
def addFailure(self, test, err):
210
158
unittest.TestResult.addFailure(self, test, err)
211
self.extractBenchmarkTime(test)
213
self.stream.writeln(" FAIL %s" % self._testTimeString())
214
elif self.dots and self.pb is None:
160
self.stream.writeln(" FAIL %s" % self._elapsedTime())
215
162
self.stream.write('F')
217
self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
218
163
self.stream.flush()
219
164
if self.stop_early:
222
167
def addSuccess(self, test):
223
self.extractBenchmarkTime(test)
225
self.stream.writeln(' OK %s' % self._testTimeString())
226
elif self.dots and self.pb is None:
169
self.stream.writeln(' OK %s' % self._elapsedTime())
227
171
self.stream.write('~')
229
self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
230
172
self.stream.flush()
231
173
unittest.TestResult.addSuccess(self, test)
233
175
def addSkipped(self, test, skip_excinfo):
234
self.extractBenchmarkTime(test)
236
print >>self.stream, ' SKIP %s' % self._testTimeString()
177
print >>self.stream, ' SKIP %s' % self._elapsedTime()
237
178
print >>self.stream, ' %s' % skip_excinfo[1]
238
elif self.dots and self.pb is None:
239
180
self.stream.write('S')
241
self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
242
181
self.stream.flush()
243
182
# seems best to treat this as success from point-of-view of unittest
244
183
# -- it actually does nothing so it barely matters :)
259
198
self.stream.writeln("%s" % err)
262
class TextTestRunner(object):
201
class TextTestRunner(unittest.TextTestRunner):
263
202
stop_on_failure = False
271
self.stream = unittest._WritelnDecorator(stream)
272
self.descriptions = descriptions
273
self.verbosity = verbosity
274
self.keep_output = keep_output
277
204
def _makeResult(self):
278
result = _MyResult(self.stream,
205
result = _MyResult(self.stream, self.descriptions, self.verbosity)
282
206
result.stop_early = self.stop_on_failure
286
"Run the given test case or test suite."
287
result = self._makeResult()
288
startTime = time.time()
289
if self.pb is not None:
290
self.pb.update('Running tests', 0, test.countTestCases())
292
stopTime = time.time()
293
timeTaken = stopTime - startTime
295
self.stream.writeln(result.separator2)
296
run = result.testsRun
297
self.stream.writeln("Ran %d test%s in %.3fs" %
298
(run, run != 1 and "s" or "", timeTaken))
299
self.stream.writeln()
300
if not result.wasSuccessful():
301
self.stream.write("FAILED (")
302
failed, errored = map(len, (result.failures, result.errors))
304
self.stream.write("failures=%d" % failed)
306
if failed: self.stream.write(", ")
307
self.stream.write("errors=%d" % errored)
308
self.stream.writeln(")")
310
self.stream.writeln("OK")
311
if self.pb is not None:
312
self.pb.update('Cleaning up', 0, 1)
313
# This is still a little bogus,
314
# but only a little. Folk not using our testrunner will
315
# have to delete their temp directories themselves.
316
test_root = TestCaseInTempDir.TEST_ROOT
317
if result.wasSuccessful() or not self.keep_output:
318
if test_root is not None:
319
osutils.rmtree(test_root)
321
if self.pb is not None:
322
self.pb.note("Failed tests working directories are in '%s'\n",
326
"Failed tests working directories are in '%s'\n" %
328
TestCaseInTempDir.TEST_ROOT = None
329
if self.pb is not None:
334
210
def iter_suite_tests(suite):
335
211
"""Return all tests in a suite, recursing through nested suites"""
607
468
handler.setLevel(logging.INFO)
608
469
logger = logging.getLogger('')
609
470
logger.addHandler(handler)
610
old_ui_factory = bzrlib.ui.ui_factory
611
bzrlib.ui.ui_factory = bzrlib.tests.blackbox.TestUIFactory(
614
bzrlib.ui.ui_factory.stdin = stdin
616
result = self.apply_redirected(stdin, stdout, stderr,
472
result = self.apply_redirected(None, stdout, stderr,
617
473
bzrlib.commands.run_bzr_catch_errors,
620
476
logger.removeHandler(handler)
621
bzrlib.ui.ui_factory = old_ui_factory
622
477
out = stdout.getvalue()
623
478
err = stderr.getvalue()
639
494
This sends the stdout/stderr results into the test's log,
640
495
where it may be useful for debugging. See also run_captured.
642
:param stdin: A string to be used as stdin for the command.
644
497
retcode = kwargs.pop('retcode', 0)
645
stdin = kwargs.pop('stdin', None)
646
return self.run_bzr_captured(args, retcode, stdin)
498
return self.run_bzr_captured(args, retcode)
648
500
def check_inventory_shape(self, inv, shape):
649
501
"""Compare an inventory to a list of expected names.
697
549
sys.stderr = real_stderr
698
550
sys.stdin = real_stdin
700
def merge(self, branch_from, wt_to):
701
"""A helper for tests to do a ui-less merge.
703
This should move to the main library when someone has time to integrate
706
# minimal ui-less merge.
707
wt_to.branch.fetch(branch_from)
708
base_rev = common_ancestor(branch_from.last_revision(),
709
wt_to.branch.last_revision(),
710
wt_to.branch.repository)
711
merge_inner(wt_to.branch, branch_from.basis_tree(),
712
wt_to.branch.repository.revision_tree(base_rev),
714
wt_to.add_pending_merge(branch_from.last_revision())
717
553
BzrTestBase = TestCase
939
774
self.assertTrue(t.is_readonly())
942
def make_branch(self, relpath, format=None):
777
def make_branch(self, relpath):
943
778
"""Create a branch on the transport at relpath."""
944
repo = self.make_repository(relpath, format=format)
779
repo = self.make_repository(relpath)
945
780
return repo.bzrdir.create_branch()
947
def make_bzrdir(self, relpath, format=None):
782
def make_bzrdir(self, relpath):
949
784
url = self.get_url(relpath)
950
785
segments = relpath.split('/')
955
790
t.mkdir(segments[-1])
956
791
except errors.FileExists:
959
format=bzrlib.bzrdir.BzrDirFormat.get_default_format()
960
# FIXME: make this use a single transport someday. RBC 20060418
961
return format.initialize_on_transport(get_transport(relpath))
793
return bzrlib.bzrdir.BzrDir.create(url)
962
794
except errors.UninitializableFormat:
963
raise TestSkipped("Format %s is not initializable." % format)
795
raise TestSkipped("Format %s is not initializable.")
965
def make_repository(self, relpath, shared=False, format=None):
797
def make_repository(self, relpath, shared=False):
966
798
"""Create a repository on our default transport at relpath."""
967
made_control = self.make_bzrdir(relpath, format=format)
799
made_control = self.make_bzrdir(relpath)
968
800
return made_control.create_repository(shared=shared)
970
def make_branch_and_tree(self, relpath, format=None):
802
def make_branch_and_tree(self, relpath):
971
803
"""Create a branch on the transport and a tree locally.
973
805
Returns the tree.
1035
867
TestCaseInTempDir._TEST_NAME = name
1041
pb = progress.ProgressBar()
1042
872
runner = TextTestRunner(stream=sys.stdout,
1044
verbosity=verbosity,
1045
keep_output=keep_output,
1047
875
runner.stop_on_failure=stop_on_failure
1048
876
if pattern != '.*':
1049
877
suite = filter_suite_by_re(suite, pattern)
1050
878
result = runner.run(suite)
879
# This is still a little bogus,
880
# but only a little. Folk not using our testrunner will
881
# have to delete their temp directories themselves.
882
test_root = TestCaseInTempDir.TEST_ROOT
883
if result.wasSuccessful() or not keep_output:
884
if test_root is not None:
885
print 'Deleting test root %s...' % test_root
887
shutil.rmtree(test_root)
891
print "Failed tests working directories are in '%s'\n" % TestCaseInTempDir.TEST_ROOT
1051
892
return result.wasSuccessful()
1054
895
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
1055
896
keep_output=False,
1057
test_suite_factory=None):
1058
898
"""Run the whole test suite under the enhanced runner"""
1059
899
global default_transport
1060
900
if transport is None:
1061
901
transport = default_transport
1062
902
old_transport = default_transport
1063
903
default_transport = transport
1065
if test_suite_factory is None:
1066
suite = test_suite()
1068
suite = test_suite_factory()
1069
906
return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
1070
907
stop_on_failure=stop_on_failure, keep_output=keep_output,
1071
908
transport=transport)
1073
910
default_transport = old_transport
1076
914
def test_suite():
1077
"""Build and return TestSuite for the whole of bzrlib.
1079
This function can be replaced if you need to change the default test
1080
suite on a global basis, but it is not encouraged.
915
"""Build and return TestSuite for the whole program."""
1082
916
from doctest import DocTestSuite
1084
918
global MODULES_TO_DOCTEST
1086
920
testmod_names = [ \
1087
921
'bzrlib.tests.test_ancestry',
922
'bzrlib.tests.test_annotate',
1088
923
'bzrlib.tests.test_api',
1089
924
'bzrlib.tests.test_bad_files',
925
'bzrlib.tests.test_basis_inventory',
1090
926
'bzrlib.tests.test_branch',
1091
927
'bzrlib.tests.test_bzrdir',
1092
928
'bzrlib.tests.test_command',
1134
968
'bzrlib.tests.test_sftp_transport',
1135
969
'bzrlib.tests.test_smart_add',
1136
970
'bzrlib.tests.test_source',
1137
'bzrlib.tests.test_status',
1138
971
'bzrlib.tests.test_store',
1139
972
'bzrlib.tests.test_symbol_versioning',
1140
973
'bzrlib.tests.test_testament',
1141
'bzrlib.tests.test_textfile',
1142
'bzrlib.tests.test_textmerge',
1143
974
'bzrlib.tests.test_trace',
1144
975
'bzrlib.tests.test_transactions',
1145
976
'bzrlib.tests.test_transform',
1146
977
'bzrlib.tests.test_transport',
1147
978
'bzrlib.tests.test_tsort',
1148
'bzrlib.tests.test_tuned_gzip',
1149
979
'bzrlib.tests.test_ui',
980
'bzrlib.tests.test_uncommit',
1150
981
'bzrlib.tests.test_upgrade',
1151
982
'bzrlib.tests.test_versionedfile',
1152
983
'bzrlib.tests.test_weave',
1157
988
test_transport_implementations = [
1158
989
'bzrlib.tests.test_transport_implementations']
991
TestCase.BZRPATH = osutils.pathjoin(
992
osutils.realpath(osutils.dirname(bzrlib.__path__[0])), 'bzr')
993
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
994
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1160
996
suite = TestSuite()
1161
loader = TestUtil.TestLoader()
997
# python2.4's TestLoader.loadTestsFromNames gives very poor
998
# errors if it fails to load a named module - no indication of what's
999
# actually wrong, just "no such module". We should probably override that
1000
# class, but for the moment just load them ourselves. (mbp 20051202)
1001
loader = TestLoader()
1162
1002
from bzrlib.transport import TransportTestProviderAdapter
1163
1003
adapter = TransportTestProviderAdapter()
1164
1004
adapt_modules(test_transport_implementations, adapter, loader, suite)
1165
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1005
for mod_name in testmod_names:
1006
mod = _load_module_by_name(mod_name)
1007
suite.addTest(loader.loadTestsFromModule(mod))
1166
1008
for package in packages_to_test():
1167
1009
suite.addTest(package.test_suite())
1168
1010
for m in MODULES_TO_TEST:
1178
1020
def adapt_modules(mods_list, adapter, loader, suite):
1179
1021
"""Adapt the modules in mods_list using adapter and add to suite."""
1180
for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
1181
suite.addTests(adapter.adapt(test))
1022
for mod_name in mods_list:
1023
mod = _load_module_by_name(mod_name)
1024
for test in iter_suite_tests(loader.loadTestsFromModule(mod)):
1025
suite.addTests(adapter.adapt(test))
1028
def _load_module_by_name(mod_name):
1029
parts = mod_name.split('.')
1030
module = __import__(mod_name)
1032
# for historical reasons python returns the top-level module even though
1033
# it loads the submodule; we need to walk down to get the one we want.
1035
module = getattr(module, parts.pop(0))