112
114
Shows output in a different format, including displaying runtime for tests.
114
116
stop_early = False
116
def _elapsedTime(self):
117
return "%5dms" % (1000 * (time.time() - self._start_time))
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)
119
161
def startTest(self, test):
120
162
unittest.TestResult.startTest(self, test)
122
164
# the beginning, but in an id, the important words are
124
166
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)
141
184
self.stream.write(what)
185
elif self.dots and self.pb is not None:
186
self.pb.update(what, self.testsRun - 1, None)
142
187
self.stream.flush()
188
self._recordTestStartTime()
190
def _recordTestStartTime(self):
191
"""Record that a test has started."""
143
192
self._start_time = time.time()
145
194
def addError(self, test, err):
146
195
if isinstance(err[1], TestSkipped):
147
196
return self.addSkipped(test, err)
148
197
unittest.TestResult.addError(self, test, err)
198
self.extractBenchmarkTime(test)
150
self.stream.writeln("ERROR %s" % self._elapsedTime())
200
self.stream.writeln("ERROR %s" % self._testTimeString())
201
elif self.dots and self.pb is None:
152
202
self.stream.write('E')
204
self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
153
205
self.stream.flush()
154
206
if self.stop_early:
157
209
def addFailure(self, test, err):
158
210
unittest.TestResult.addFailure(self, test, err)
211
self.extractBenchmarkTime(test)
160
self.stream.writeln(" FAIL %s" % self._elapsedTime())
213
self.stream.writeln(" FAIL %s" % self._testTimeString())
214
elif self.dots and self.pb is None:
162
215
self.stream.write('F')
217
self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
163
218
self.stream.flush()
164
219
if self.stop_early:
167
222
def addSuccess(self, test):
223
self.extractBenchmarkTime(test)
169
self.stream.writeln(' OK %s' % self._elapsedTime())
225
self.stream.writeln(' OK %s' % self._testTimeString())
226
elif self.dots and self.pb is None:
171
227
self.stream.write('~')
229
self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
172
230
self.stream.flush()
173
231
unittest.TestResult.addSuccess(self, test)
175
233
def addSkipped(self, test, skip_excinfo):
234
self.extractBenchmarkTime(test)
177
print >>self.stream, ' SKIP %s' % self._elapsedTime()
236
print >>self.stream, ' SKIP %s' % self._testTimeString()
178
237
print >>self.stream, ' %s' % skip_excinfo[1]
238
elif self.dots and self.pb is None:
180
239
self.stream.write('S')
241
self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
181
242
self.stream.flush()
182
243
# seems best to treat this as success from point-of-view of unittest
183
244
# -- it actually does nothing so it barely matters :)
198
259
self.stream.writeln("%s" % err)
201
class TextTestRunner(unittest.TextTestRunner):
262
class TextTestRunner(object):
202
263
stop_on_failure = False
271
self.stream = unittest._WritelnDecorator(stream)
272
self.descriptions = descriptions
273
self.verbosity = verbosity
274
self.keep_output = keep_output
204
277
def _makeResult(self):
205
result = _MyResult(self.stream, self.descriptions, self.verbosity)
278
result = _MyResult(self.stream,
206
282
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:
210
334
def iter_suite_tests(suite):
211
335
"""Return all tests in a suite, recursing through nested suites"""
468
607
handler.setLevel(logging.INFO)
469
608
logger = logging.getLogger('')
470
609
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
472
result = self.apply_redirected(None, stdout, stderr,
616
result = self.apply_redirected(stdin, stdout, stderr,
473
617
bzrlib.commands.run_bzr_catch_errors,
476
620
logger.removeHandler(handler)
621
bzrlib.ui.ui_factory = old_ui_factory
477
622
out = stdout.getvalue()
478
623
err = stderr.getvalue()
494
639
This sends the stdout/stderr results into the test's log,
495
640
where it may be useful for debugging. See also run_captured.
642
:param stdin: A string to be used as stdin for the command.
497
644
retcode = kwargs.pop('retcode', 0)
498
return self.run_bzr_captured(args, retcode)
645
stdin = kwargs.pop('stdin', None)
646
return self.run_bzr_captured(args, retcode, stdin)
500
648
def check_inventory_shape(self, inv, shape):
501
649
"""Compare an inventory to a list of expected names.
549
697
sys.stderr = real_stderr
550
698
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())
553
717
BzrTestBase = TestCase
775
939
self.assertTrue(t.is_readonly())
778
def make_branch(self, relpath):
942
def make_branch(self, relpath, format=None):
779
943
"""Create a branch on the transport at relpath."""
780
repo = self.make_repository(relpath)
944
repo = self.make_repository(relpath, format=format)
781
945
return repo.bzrdir.create_branch()
783
def make_bzrdir(self, relpath):
947
def make_bzrdir(self, relpath, format=None):
785
949
url = self.get_url(relpath)
786
950
segments = relpath.split('/')
791
955
t.mkdir(segments[-1])
792
956
except errors.FileExists:
794
return bzrlib.bzrdir.BzrDir.create(url)
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))
795
962
except errors.UninitializableFormat:
796
raise TestSkipped("Format %s is not initializable.")
963
raise TestSkipped("Format %s is not initializable." % format)
798
def make_repository(self, relpath, shared=False):
965
def make_repository(self, relpath, shared=False, format=None):
799
966
"""Create a repository on our default transport at relpath."""
800
made_control = self.make_bzrdir(relpath)
967
made_control = self.make_bzrdir(relpath, format=format)
801
968
return made_control.create_repository(shared=shared)
803
def make_branch_and_tree(self, relpath):
970
def make_branch_and_tree(self, relpath, format=None):
804
971
"""Create a branch on the transport and a tree locally.
806
973
Returns the tree.
868
1035
TestCaseInTempDir._TEST_NAME = name
1041
pb = progress.ProgressBar()
873
1042
runner = TextTestRunner(stream=sys.stdout,
1044
verbosity=verbosity,
1045
keep_output=keep_output,
876
1047
runner.stop_on_failure=stop_on_failure
877
1048
if pattern != '.*':
878
1049
suite = filter_suite_by_re(suite, pattern)
879
1050
result = runner.run(suite)
880
# This is still a little bogus,
881
# but only a little. Folk not using our testrunner will
882
# have to delete their temp directories themselves.
883
test_root = TestCaseInTempDir.TEST_ROOT
884
if result.wasSuccessful() or not keep_output:
885
if test_root is not None:
886
print 'Deleting test root %s...' % test_root
888
shutil.rmtree(test_root)
892
print "Failed tests working directories are in '%s'\n" % TestCaseInTempDir.TEST_ROOT
893
1051
return result.wasSuccessful()
896
1054
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
897
1055
keep_output=False,
1057
test_suite_factory=None):
899
1058
"""Run the whole test suite under the enhanced runner"""
900
1059
global default_transport
901
1060
if transport is None:
902
1061
transport = default_transport
903
1062
old_transport = default_transport
904
1063
default_transport = transport
1065
if test_suite_factory is None:
1066
suite = test_suite()
1068
suite = test_suite_factory()
907
1069
return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
908
1070
stop_on_failure=stop_on_failure, keep_output=keep_output,
909
1071
transport=transport)
911
1073
default_transport = old_transport
915
1076
def test_suite():
916
"""Build and return TestSuite for the whole program."""
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.
917
1082
from doctest import DocTestSuite
919
1084
global MODULES_TO_DOCTEST
921
1086
testmod_names = [ \
922
1087
'bzrlib.tests.test_ancestry',
923
'bzrlib.tests.test_annotate',
924
1088
'bzrlib.tests.test_api',
925
1089
'bzrlib.tests.test_bad_files',
926
'bzrlib.tests.test_basis_inventory',
927
1090
'bzrlib.tests.test_branch',
928
1091
'bzrlib.tests.test_bzrdir',
929
1092
'bzrlib.tests.test_command',
969
1134
'bzrlib.tests.test_sftp_transport',
970
1135
'bzrlib.tests.test_smart_add',
971
1136
'bzrlib.tests.test_source',
1137
'bzrlib.tests.test_status',
972
1138
'bzrlib.tests.test_store',
973
1139
'bzrlib.tests.test_symbol_versioning',
974
1140
'bzrlib.tests.test_testament',
1141
'bzrlib.tests.test_textfile',
1142
'bzrlib.tests.test_textmerge',
975
1143
'bzrlib.tests.test_trace',
976
1144
'bzrlib.tests.test_transactions',
977
1145
'bzrlib.tests.test_transform',
978
1146
'bzrlib.tests.test_transport',
979
1147
'bzrlib.tests.test_tsort',
1148
'bzrlib.tests.test_tuned_gzip',
980
1149
'bzrlib.tests.test_ui',
981
'bzrlib.tests.test_uncommit',
982
1150
'bzrlib.tests.test_upgrade',
983
1151
'bzrlib.tests.test_versionedfile',
984
1152
'bzrlib.tests.test_weave',
989
1157
test_transport_implementations = [
990
1158
'bzrlib.tests.test_transport_implementations']
992
TestCase.BZRPATH = osutils.pathjoin(
993
osutils.realpath(osutils.dirname(bzrlib.__path__[0])), 'bzr')
994
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
995
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
997
1160
suite = TestSuite()
998
# python2.4's TestLoader.loadTestsFromNames gives very poor
999
# errors if it fails to load a named module - no indication of what's
1000
# actually wrong, just "no such module". We should probably override that
1001
# class, but for the moment just load them ourselves. (mbp 20051202)
1002
loader = TestLoader()
1161
loader = TestUtil.TestLoader()
1003
1162
from bzrlib.transport import TransportTestProviderAdapter
1004
1163
adapter = TransportTestProviderAdapter()
1005
1164
adapt_modules(test_transport_implementations, adapter, loader, suite)
1006
for mod_name in testmod_names:
1007
mod = _load_module_by_name(mod_name)
1008
suite.addTest(loader.loadTestsFromModule(mod))
1165
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1009
1166
for package in packages_to_test():
1010
1167
suite.addTest(package.test_suite())
1011
1168
for m in MODULES_TO_TEST:
1021
1178
def adapt_modules(mods_list, adapter, loader, suite):
1022
1179
"""Adapt the modules in mods_list using adapter and add to suite."""
1023
for mod_name in mods_list:
1024
mod = _load_module_by_name(mod_name)
1025
for test in iter_suite_tests(loader.loadTestsFromModule(mod)):
1026
suite.addTests(adapter.adapt(test))
1029
def _load_module_by_name(mod_name):
1030
parts = mod_name.split('.')
1031
module = __import__(mod_name)
1033
# for historical reasons python returns the top-level module even though
1034
# it loads the submodule; we need to walk down to get the one we want.
1036
module = getattr(module, parts.pop(0))
1180
for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
1181
suite.addTests(adapter.adapt(test))