~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/__init__.py

Merge in format-5 work - release bzr 0.1rc1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
import errno
25
25
import subprocess
26
26
import shutil
27
 
import testsweet
 
27
import re
28
28
 
29
29
import bzrlib.commands
30
30
import bzrlib.trace
31
31
import bzrlib.fetch
 
32
from bzrlib.selftest import TestUtil
 
33
from bzrlib.selftest.TestUtil import TestLoader, TestSuite
32
34
 
33
35
 
34
36
MODULES_TO_TEST = []
36
38
 
37
39
from logging import debug, warning, error
38
40
 
 
41
 
 
42
 
 
43
class EarlyStoppingTestResultAdapter(object):
 
44
    """An adapter for TestResult to stop at the first first failure or error"""
 
45
 
 
46
    def __init__(self, result):
 
47
        self._result = result
 
48
 
 
49
    def addError(self, test, err):
 
50
        self._result.addError(test, err)
 
51
        self._result.stop()
 
52
 
 
53
    def addFailure(self, test, err):
 
54
        self._result.addFailure(test, err)
 
55
        self._result.stop()
 
56
 
 
57
    def __getattr__(self, name):
 
58
        return getattr(self._result, name)
 
59
 
 
60
    def __setattr__(self, name, value):
 
61
        if name == '_result':
 
62
            object.__setattr__(self, name, value)
 
63
        return setattr(self._result, name, value)
 
64
 
 
65
 
 
66
class _MyResult(unittest._TextTestResult):
 
67
    """
 
68
    Custom TestResult.
 
69
 
 
70
    No special behaviour for now.
 
71
    """
 
72
 
 
73
    def startTest(self, test):
 
74
        unittest.TestResult.startTest(self, test)
 
75
        # TODO: Maybe show test.shortDescription somewhere?
 
76
        what = test.shortDescription() or test.id()        
 
77
        if self.showAll:
 
78
            self.stream.write('%-70.70s' % what)
 
79
        self.stream.flush()
 
80
 
 
81
    def addError(self, test, err):
 
82
        super(_MyResult, self).addError(test, err)
 
83
        self.stream.flush()
 
84
 
 
85
    def addFailure(self, test, err):
 
86
        super(_MyResult, self).addFailure(test, err)
 
87
        self.stream.flush()
 
88
 
 
89
    def addSuccess(self, test):
 
90
        if self.showAll:
 
91
            self.stream.writeln('OK')
 
92
        elif self.dots:
 
93
            self.stream.write('~')
 
94
        self.stream.flush()
 
95
        unittest.TestResult.addSuccess(self, test)
 
96
 
 
97
    def printErrorList(self, flavour, errors):
 
98
        for test, err in errors:
 
99
            self.stream.writeln(self.separator1)
 
100
            self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
 
101
            if hasattr(test, '_get_log'):
 
102
                self.stream.writeln()
 
103
                self.stream.writeln('log from this test:')
 
104
                print >>self.stream, test._get_log()
 
105
            self.stream.writeln(self.separator2)
 
106
            self.stream.writeln("%s" % err)
 
107
 
 
108
 
 
109
class TextTestRunner(unittest.TextTestRunner):
 
110
 
 
111
    def _makeResult(self):
 
112
        result = _MyResult(self.stream, self.descriptions, self.verbosity)
 
113
        return EarlyStoppingTestResultAdapter(result)
 
114
 
 
115
 
 
116
def iter_suite_tests(suite):
 
117
    """Return all tests in a suite, recursing through nested suites"""
 
118
    for item in suite._tests:
 
119
        if isinstance(item, unittest.TestCase):
 
120
            yield item
 
121
        elif isinstance(item, unittest.TestSuite):
 
122
            for r in iter_suite_tests(item):
 
123
                yield r
 
124
        else:
 
125
            raise Exception('unknown object %r inside test suite %r'
 
126
                            % (item, suite))
 
127
 
 
128
 
 
129
class TestSkipped(Exception):
 
130
    """Indicates that a test was intentionally skipped, rather than failing."""
 
131
    # XXX: Not used yet
 
132
 
 
133
 
39
134
class CommandFailed(Exception):
40
135
    pass
41
136
 
55
150
    BZRPATH = 'bzr'
56
151
 
57
152
    def setUp(self):
58
 
        # this replaces the default testsweet.TestCase; we don't want logging changed
59
153
        unittest.TestCase.setUp(self)
60
154
        bzrlib.trace.disable_default_logging()
61
155
        self._enable_file_logging()
68
162
 
69
163
        hdlr = logging.StreamHandler(self._log_file)
70
164
        hdlr.setLevel(logging.DEBUG)
71
 
        hdlr.setFormatter(logging.Formatter('%(levelname)4.4s  %(message)s'))
 
165
        hdlr.setFormatter(logging.Formatter('%(levelname)8s  %(message)s'))
72
166
        logging.getLogger('').addHandler(hdlr)
73
167
        logging.getLogger('').setLevel(logging.DEBUG)
74
168
        self._log_hdlr = hdlr
153
247
        return self.run_bzr_captured(args, retcode)
154
248
 
155
249
    def check_inventory_shape(self, inv, shape):
156
 
        """
157
 
        Compare an inventory to a list of expected names.
 
250
        """Compare an inventory to a list of expected names.
158
251
 
159
252
        Fail if they are not precisely equal.
160
253
        """
232
325
        if contents != expect:
233
326
            self.log("expected: %r" % expect)
234
327
            self.log("actually: %r" % contents)
235
 
            self.fail("contents of %s not as expected")
 
328
            self.fail("contents of %s not as expected" % filename)
236
329
 
237
330
    def _make_test_root(self):
238
331
        if TestCaseInTempDir.TEST_ROOT is not None:
259
352
        super(TestCaseInTempDir, self).setUp()
260
353
        self._make_test_root()
261
354
        self._currentdir = os.getcwdu()
262
 
        self.test_dir = os.path.join(self.TEST_ROOT, self.id())
 
355
        short_id = self.id().replace('bzrlib.selftest.', '') \
 
356
                   .replace('__main__.', '')
 
357
        self.test_dir = os.path.join(self.TEST_ROOT, short_id)
263
358
        os.mkdir(self.test_dir)
264
359
        os.chdir(self.test_dir)
265
360
        
285
380
                print >>f, "contents of", name
286
381
                f.close()
287
382
 
 
383
    def failUnlessExists(self, path):
 
384
        """Fail unless path, which may be abs or relative, exists."""
 
385
        self.failUnless(os.path.exists(path))
 
386
        
288
387
 
289
388
class MetaTestLog(TestCase):
290
389
    def test_logging(self):
295
394
        ##assert 0
296
395
 
297
396
 
298
 
def selftest(verbose=False, pattern=".*"):
299
 
    return testsweet.run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern)
 
397
def filter_suite_by_re(suite, pattern):
 
398
    result = TestUtil.TestSuite()
 
399
    filter_re = re.compile(pattern)
 
400
    for test in iter_suite_tests(suite):
 
401
        if filter_re.match(test.id()):
 
402
            result.addTest(test)
 
403
    return result
 
404
 
 
405
 
 
406
def filter_suite_by_names(suite, wanted_names):
 
407
    """Return a new suite containing only selected tests.
 
408
    
 
409
    Names are considered to match if any name is a substring of the 
 
410
    fully-qualified test id (i.e. the class ."""
 
411
    result = TestSuite()
 
412
    for test in iter_suite_tests(suite):
 
413
        this_id = test.id()
 
414
        for p in wanted_names:
 
415
            if this_id.find(p) != -1:
 
416
                result.addTest(test)
 
417
    return result
 
418
 
 
419
 
 
420
def run_suite(suite, name='test', verbose=False, pattern=".*", testnames=None):
 
421
    TestCaseInTempDir._TEST_NAME = name
 
422
    if verbose:
 
423
        verbosity = 2
 
424
    else:
 
425
        verbosity = 1
 
426
    runner = TextTestRunner(stream=sys.stdout,
 
427
                            descriptions=0,
 
428
                            verbosity=verbosity)
 
429
    if testnames:
 
430
        suite = filter_suite_by_names(suite, testnames)
 
431
    if pattern != '.*':
 
432
        suite = filter_suite_by_re(suite, pattern)
 
433
    result = runner.run(suite)
 
434
    # This is still a little bogus, 
 
435
    # but only a little. Folk not using our testrunner will
 
436
    # have to delete their temp directories themselves.
 
437
    if result.wasSuccessful():
 
438
        if TestCaseInTempDir.TEST_ROOT is not None:
 
439
            shutil.rmtree(TestCaseInTempDir.TEST_ROOT) 
 
440
    else:
 
441
        print "Failed tests working directories are in '%s'\n" % TestCaseInTempDir.TEST_ROOT
 
442
    return result.wasSuccessful()
 
443
 
 
444
 
 
445
def selftest(verbose=False, pattern=".*", testnames=None):
 
446
    """Run the whole test suite under the enhanced runner"""
 
447
    return run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern,
 
448
                     testnames=testnames)
300
449
 
301
450
 
302
451
def test_suite():
303
 
    from bzrlib.selftest.TestUtil import TestLoader, TestSuite
304
 
    import bzrlib, bzrlib.store, bzrlib.inventory, bzrlib.branch
305
 
    import bzrlib.osutils, bzrlib.commands, bzrlib.merge3, bzrlib.plugin
 
452
    """Build and return TestSuite for the whole program."""
 
453
    import bzrlib.store, bzrlib.inventory, bzrlib.branch
 
454
    import bzrlib.osutils, bzrlib.merge3, bzrlib.plugin
306
455
    from doctest import DocTestSuite
307
456
 
308
457
    global MODULES_TO_TEST, MODULES_TO_DOCTEST
309
458
 
310
459
    testmod_names = \
311
460
                  ['bzrlib.selftest.MetaTestLog',
312
 
                   'bzrlib.selftest.test_parent',
313
461
                   'bzrlib.selftest.testinv',
314
 
                   'bzrlib.selftest.testfetch',
 
462
                   'bzrlib.selftest.test_ancestry',
 
463
                   'bzrlib.selftest.test_commit',
 
464
                   'bzrlib.selftest.test_commit_merge',
315
465
                   'bzrlib.selftest.versioning',
316
 
                   'bzrlib.selftest.whitebox',
317
466
                   'bzrlib.selftest.testmerge3',
318
467
                   'bzrlib.selftest.testmerge',
319
468
                   'bzrlib.selftest.testhashcache',
320
469
                   'bzrlib.selftest.teststatus',
321
470
                   'bzrlib.selftest.testlog',
322
 
                   'bzrlib.selftest.blackbox',
323
471
                   'bzrlib.selftest.testrevisionnamespaces',
324
472
                   'bzrlib.selftest.testbranch',
325
 
                   'bzrlib.selftest.testremotebranch',
326
473
                   'bzrlib.selftest.testrevision',
327
474
                   'bzrlib.selftest.test_revision_info',
328
475
                   'bzrlib.selftest.test_merge_core',
329
476
                   'bzrlib.selftest.test_smart_add',
330
477
                   'bzrlib.selftest.test_bad_files',
331
478
                   'bzrlib.selftest.testdiff',
 
479
                   'bzrlib.selftest.test_parent',
332
480
                   'bzrlib.selftest.test_xml',
333
 
                   'bzrlib.fetch',
 
481
                   'bzrlib.selftest.test_weave',
 
482
                   'bzrlib.selftest.testfetch',
 
483
                   'bzrlib.selftest.whitebox',
334
484
                   'bzrlib.selftest.teststore',
 
485
                   'bzrlib.selftest.blackbox',
 
486
                   'bzrlib.selftest.testtransport',
335
487
                   'bzrlib.selftest.testgraph',
 
488
                   'bzrlib.selftest.testworkingtree',
 
489
                   'bzrlib.selftest.test_upgrade',
336
490
                   ]
337
491
 
338
492
    for m in (bzrlib.store, bzrlib.inventory, bzrlib.branch,