37
38
from logging import debug, warning, error
42
class EarlyStoppingTestResultAdapter(object):
43
"""An adapter for TestResult to stop at the first first failure or error"""
45
def __init__(self, result):
48
def addError(self, test, err):
49
self._result.addError(test, err)
52
def addFailure(self, test, err):
53
self._result.addFailure(test, err)
56
def __getattr__(self, name):
57
return getattr(self._result, name)
59
def __setattr__(self, name, value):
61
object.__setattr__(self, name, value)
62
return setattr(self._result, name, value)
65
class _MyResult(unittest._TextTestResult):
69
No special behaviour for now.
72
def startTest(self, test):
73
unittest.TestResult.startTest(self, test)
74
# TODO: Maybe show test.shortDescription somewhere?
75
what = test.shortDescription() or test.id()
77
self.stream.write('%-70.70s' % what)
80
def addError(self, test, err):
81
super(_MyResult, self).addError(test, err)
84
def addFailure(self, test, err):
85
super(_MyResult, self).addFailure(test, err)
88
def addSuccess(self, test):
90
self.stream.writeln('OK')
92
self.stream.write('~')
94
unittest.TestResult.addSuccess(self, test)
96
def printErrorList(self, flavour, errors):
97
for test, err in errors:
98
self.stream.writeln(self.separator1)
99
self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
100
if hasattr(test, '_get_log'):
101
self.stream.writeln()
102
self.stream.writeln('log from this test:')
103
print >>self.stream, test._get_log()
104
self.stream.writeln(self.separator2)
105
self.stream.writeln("%s" % err)
108
class TextTestRunner(unittest.TextTestRunner):
110
def _makeResult(self):
111
result = _MyResult(self.stream, self.descriptions, self.verbosity)
112
return EarlyStoppingTestResultAdapter(result)
115
class filteringVisitor(TestUtil.TestVisitor):
116
"""I accruse all the testCases I visit that pass a regexp filter on id
120
def __init__(self, filter):
122
TestUtil.TestVisitor.__init__(self)
124
self.filter=re.compile(filter)
127
"""answer the suite we are building"""
128
if self._suite is None:
129
self._suite=TestUtil.TestSuite()
132
def visitCase(self, aCase):
133
if self.filter.match(aCase.id()):
134
self.suite().addTest(aCase)
136
class TestSkipped(Exception):
137
"""Indicates that a test was intentionally skipped, rather than failing."""
39
141
class CommandFailed(Exception):
92
191
"""Return as a string the log for this test"""
93
192
return open(self._log_file_name).read()
195
def capture(self, cmd):
196
"""Shortcut that splits cmd into words, runs, and returns stdout"""
197
return self.run_bzr_captured(cmd.split())[0]
199
def run_bzr_captured(self, argv, retcode=0):
200
"""Invoke bzr and return (result, stdout, stderr).
202
Useful for code that wants to check the contents of the
203
output, the way error messages are presented, etc.
205
This should be the main method for tests that want to exercise the
206
overall behavior of the bzr application (rather than a unit test
207
or a functional test of the library.)
209
Much of the old code runs bzr by forking a new copy of Python, but
210
that is slower, harder to debug, and generally not necessary.
212
This runs bzr through the interface that catches and reports
213
errors, and with logging set to something approximating the
214
default, so that error reporting can be checked.
216
argv -- arguments to invoke bzr
217
retcode -- expected return code, or None for don't-care.
221
self.log('run bzr: %s', ' '.join(argv))
222
handler = logging.StreamHandler(stderr)
223
handler.setFormatter(bzrlib.trace.QuietFormatter())
224
handler.setLevel(logging.INFO)
225
logger = logging.getLogger('')
226
logger.addHandler(handler)
228
result = self.apply_redirected(None, stdout, stderr,
229
bzrlib.commands.run_bzr_catch_errors,
232
logger.removeHandler(handler)
233
out = stdout.getvalue()
234
err = stderr.getvalue()
236
self.log('output:\n%s', out)
238
self.log('errors:\n%s', err)
239
if retcode is not None:
240
self.assertEquals(result, retcode)
95
243
def run_bzr(self, *args, **kwargs):
96
244
"""Invoke bzr, as if it were run from the command line.
99
247
overall behavior of the bzr application (rather than a unit test
100
248
or a functional test of the library.)
102
Much of the old code runs bzr by forking a new copy of Python, but
103
that is slower, harder to debug, and generally not necessary.
250
This sends the stdout/stderr results into the test's log,
251
where it may be useful for debugging. See also run_captured.
105
retcode = kwargs.get('retcode', 0)
106
result = self.apply_redirected(None, None, None,
107
bzrlib.commands.run_bzr, args)
108
self.assertEquals(result, retcode)
253
retcode = kwargs.pop('retcode', 0)
254
return self.run_bzr_captured(args, retcode)
111
256
def check_inventory_shape(self, inv, shape):
113
Compare an inventory to a list of expected names.
257
"""Compare an inventory to a list of expected names.
115
259
Fail if they are not precisely equal.
218
366
os.chdir(self.test_dir)
220
368
def tearDown(self):
222
369
os.chdir(self._currentdir)
223
370
super(TestCaseInTempDir, self).tearDown()
225
def _formcmd(self, cmd):
226
if isinstance(cmd, basestring):
229
cmd[0] = self.BZRPATH
230
if self.OVERRIDE_PYTHON:
231
cmd.insert(0, self.OVERRIDE_PYTHON)
232
self.log('$ %r' % cmd)
235
def runcmd(self, cmd, retcode=0):
236
"""Run one command and check the return code.
238
Returns a tuple of (stdout,stderr) strings.
240
If a single string is based, it is split into words.
241
For commands that are not simple space-separated words, please
242
pass a list instead."""
243
cmd = self._formcmd(cmd)
244
self.log('$ ' + ' '.join(cmd))
245
actual_retcode = subprocess.call(cmd, stdout=self._log_file,
246
stderr=self._log_file)
247
if retcode != actual_retcode:
248
raise CommandFailed("test failed: %r returned %d, expected %d"
249
% (cmd, actual_retcode, retcode))
251
def backtick(self, cmd, retcode=0):
252
"""Run a command and return its output"""
253
cmd = self._formcmd(cmd)
254
child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=self._log_file)
255
outd, errd = child.communicate()
257
actual_retcode = child.wait()
259
outd = outd.replace('\r', '')
261
if retcode != actual_retcode:
262
raise CommandFailed("test failed: %r returned %d, expected %d"
263
% (cmd, actual_retcode, retcode))
269
372
def build_tree(self, shape):
270
373
"""Build a test tree according to a pattern.
401
def run_suite(suite, name='test', verbose=False, pattern=".*"):
402
TestCaseInTempDir._TEST_NAME = name
407
runner = TextTestRunner(stream=sys.stdout,
410
visitor = filteringVisitor(pattern)
412
result = runner.run(visitor.suite())
413
# This is still a little bogus,
414
# but only a little. Folk not using our testrunner will
415
# have to delete their temp directories themselves.
416
if result.wasSuccessful():
417
if TestCaseInTempDir.TEST_ROOT is not None:
418
shutil.rmtree(TestCaseInTempDir.TEST_ROOT)
420
print "Failed tests working directories are in '%s'\n" % TestCaseInTempDir.TEST_ROOT
421
return result.wasSuccessful()
299
424
def selftest(verbose=False, pattern=".*"):
300
425
"""Run the whole test suite under the enhanced runner"""
301
return testsweet.run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern)
426
return run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern)
304
429
def test_suite():
305
430
"""Build and return TestSuite for the whole program."""
306
from bzrlib.selftest.TestUtil import TestLoader, TestSuite
307
import bzrlib, bzrlib.store, bzrlib.inventory, bzrlib.branch
308
import bzrlib.osutils, bzrlib.commands, bzrlib.merge3, bzrlib.plugin
431
import bzrlib.store, bzrlib.inventory, bzrlib.branch
432
import bzrlib.osutils, bzrlib.merge3, bzrlib.plugin
309
433
from doctest import DocTestSuite
315
435
global MODULES_TO_TEST, MODULES_TO_DOCTEST
317
437
testmod_names = \
318
438
['bzrlib.selftest.MetaTestLog',
319
439
'bzrlib.selftest.testinv',
440
'bzrlib.selftest.test_ancestry',
441
'bzrlib.selftest.test_commit',
442
'bzrlib.selftest.test_commit_merge',
320
443
'bzrlib.selftest.versioning',
321
444
'bzrlib.selftest.testmerge3',
445
'bzrlib.selftest.testmerge',
322
446
'bzrlib.selftest.testhashcache',
323
447
'bzrlib.selftest.teststatus',
324
448
'bzrlib.selftest.testlog',
325
449
'bzrlib.selftest.testrevisionnamespaces',
326
450
'bzrlib.selftest.testbranch',
327
# 'bzrlib.selftest.testrevision',
328
# 'bzrlib.selftest.test_merge_core',
451
'bzrlib.selftest.testrevision',
452
'bzrlib.selftest.test_revision_info',
453
'bzrlib.selftest.test_merge_core',
329
454
'bzrlib.selftest.test_smart_add',
455
'bzrlib.selftest.test_bad_files',
330
456
'bzrlib.selftest.testdiff',
331
# 'bzrlib.selftest.test_parent',
457
'bzrlib.selftest.test_parent',
332
458
'bzrlib.selftest.test_xml',
333
# 'bzrlib.selftest.testfetch',
334
# 'bzrlib.selftest.whitebox',
459
'bzrlib.selftest.test_weave',
460
'bzrlib.selftest.testfetch',
461
'bzrlib.selftest.whitebox',
335
462
'bzrlib.selftest.teststore',
336
# 'bzrlib.selftest.blackbox',
463
'bzrlib.selftest.blackbox',
464
'bzrlib.selftest.testtransport',
465
'bzrlib.selftest.testgraph',
466
'bzrlib.selftest.testworkingtree',
467
'bzrlib.selftest.test_upgrade',
339
470
for m in (bzrlib.store, bzrlib.inventory, bzrlib.branch,