~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/__init__.py

  • Committer: Robert Collins
  • Date: 2005-10-08 00:39:04 UTC
  • mfrom: (1185.1.52)
  • Revision ID: robertc@robertcollins.net-20051008003904-aaffaea2778efe3e
merge in martins reweave, integrated to fetch, and a bugfix for commit and upgrade with executable files

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
 
18
18
from cStringIO import StringIO
19
 
import difflib
20
 
import errno
21
19
import logging
 
20
import unittest
 
21
import tempfile
22
22
import os
 
23
import sys
 
24
import errno
 
25
import subprocess
 
26
import shutil
23
27
import re
24
 
import shutil
25
 
import sys
26
 
import tempfile
27
 
import unittest
28
 
import time
29
28
 
30
29
import bzrlib.commands
31
30
import bzrlib.trace
32
31
import bzrlib.fetch
33
 
import bzrlib.osutils as osutils
34
32
from bzrlib.selftest import TestUtil
35
33
from bzrlib.selftest.TestUtil import TestLoader, TestSuite
36
 
from bzrlib.selftest.treeshape import build_tree_contents
 
34
 
37
35
 
38
36
MODULES_TO_TEST = []
39
37
MODULES_TO_DOCTEST = []
72
70
    No special behaviour for now.
73
71
    """
74
72
 
75
 
    def _elapsedTime(self):
76
 
        return "(Took %.3fs)" % (time.time() - self._start_time)
77
 
 
78
73
    def startTest(self, test):
79
74
        unittest.TestResult.startTest(self, test)
80
75
        # TODO: Maybe show test.shortDescription somewhere?
82
77
        if self.showAll:
83
78
            self.stream.write('%-70.70s' % what)
84
79
        self.stream.flush()
85
 
        self._start_time = time.time()
86
80
 
87
81
    def addError(self, test, err):
88
 
        unittest.TestResult.addError(self, test, err)
89
 
        if self.showAll:
90
 
            self.stream.writeln("ERROR %s" % self._elapsedTime())
91
 
        elif self.dots:
92
 
            self.stream.write('E')
 
82
        super(_MyResult, self).addError(test, err)
93
83
        self.stream.flush()
94
84
 
95
85
    def addFailure(self, test, err):
96
 
        unittest.TestResult.addFailure(self, test, err)
97
 
        if self.showAll:
98
 
            self.stream.writeln("FAIL %s" % self._elapsedTime())
99
 
        elif self.dots:
100
 
            self.stream.write('F')
 
86
        super(_MyResult, self).addFailure(test, err)
101
87
        self.stream.flush()
102
88
 
103
89
    def addSuccess(self, test):
104
90
        if self.showAll:
105
 
            self.stream.writeln('OK %s' % self._elapsedTime())
 
91
            self.stream.writeln('OK')
106
92
        elif self.dots:
107
93
            self.stream.write('~')
108
94
        self.stream.flush()
121
107
 
122
108
 
123
109
class TextTestRunner(unittest.TextTestRunner):
124
 
    stop_on_failure = False
125
110
 
126
111
    def _makeResult(self):
127
112
        result = _MyResult(self.stream, self.descriptions, self.verbosity)
128
 
        if self.stop_on_failure:
129
 
            result = EarlyStoppingTestResultAdapter(result)
130
 
        return result
 
113
        return EarlyStoppingTestResultAdapter(result)
131
114
 
132
115
 
133
116
def iter_suite_tests(suite):
165
148
    routine, and to build and check bzr trees."""
166
149
 
167
150
    BZRPATH = 'bzr'
168
 
    _log_file_name = None
169
151
 
170
152
    def setUp(self):
171
153
        unittest.TestCase.setUp(self)
172
 
        self.oldenv = os.environ.get('HOME', None)
173
 
        os.environ['HOME'] = os.getcwd()
174
 
        self.bzr_email = os.environ.get('BZREMAIL')
175
 
        if self.bzr_email is not None:
176
 
            del os.environ['BZREMAIL']
177
 
        self.email = os.environ.get('EMAIL')
178
 
        if self.email is not None:
179
 
            del os.environ['EMAIL']
180
154
        bzrlib.trace.disable_default_logging()
181
155
        self._enable_file_logging()
182
156
 
183
 
    def _ndiff_strings(self, a, b):
184
 
        """Return ndiff between two strings containing lines.
185
 
        
186
 
        A trailing newline is added if missing to make the strings
187
 
        print properly."""
188
 
        if b and b[-1] != '\n':
189
 
            b += '\n'
190
 
        if a and a[-1] != '\n':
191
 
            a += '\n'
192
 
        difflines = difflib.ndiff(a.splitlines(True),
193
 
                                  b.splitlines(True),
194
 
                                  linejunk=lambda x: False,
195
 
                                  charjunk=lambda x: False)
196
 
        return ''.join(difflines)
197
 
 
198
 
    def assertEqualDiff(self, a, b):
199
 
        """Assert two texts are equal, if not raise an exception.
200
 
        
201
 
        This is intended for use with multi-line strings where it can 
202
 
        be hard to find the differences by eye.
203
 
        """
204
 
        # TODO: perhaps override assertEquals to call this for strings?
205
 
        if a == b:
206
 
            return
207
 
        raise AssertionError("texts not equal:\n" + 
208
 
                             self._ndiff_strings(a, b))      
209
 
 
210
 
    def assertContainsRe(self, haystack, needle_re):
211
 
        """Assert that a contains something matching a regular expression."""
212
 
        if not re.search(needle_re, haystack):
213
 
            raise AssertionError('pattern "%s" not found in "%s"'
214
 
                    % (needle_re, haystack))
215
157
 
216
158
    def _enable_file_logging(self):
217
159
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
229
171
        self._log_file_name = name
230
172
 
231
173
    def tearDown(self):
232
 
        os.environ['HOME'] = self.oldenv
233
 
        if os.environ.get('BZREMAIL') is not None:
234
 
            del os.environ['BZREMAIL']
235
 
        if self.bzr_email is not None:
236
 
            os.environ['BZREMAIL'] = self.bzr_email
237
 
        if os.environ.get('EMAIL') is not None:
238
 
            del os.environ['EMAIL']
239
 
        if self.email is not None:
240
 
            os.environ['EMAIL'] = self.email
241
174
        logging.getLogger('').removeHandler(self._log_hdlr)
242
175
        bzrlib.trace.enable_default_logging()
243
176
        logging.debug('%s teardown', self.id())
249
182
 
250
183
    def _get_log(self):
251
184
        """Return as a string the log for this test"""
252
 
        if self._log_file_name:
253
 
            return open(self._log_file_name).read()
254
 
        else:
255
 
            return ''
 
185
        return open(self._log_file_name).read()
 
186
 
256
187
 
257
188
    def capture(self, cmd):
258
189
        """Shortcut that splits cmd into words, runs, and returns stdout"""
418
349
        os.mkdir(os.path.join(TestCaseInTempDir.TEST_ROOT, '.bzr'))
419
350
 
420
351
    def setUp(self):
 
352
        super(TestCaseInTempDir, self).setUp()
421
353
        self._make_test_root()
422
354
        self._currentdir = os.getcwdu()
423
355
        short_id = self.id().replace('bzrlib.selftest.', '') \
425
357
        self.test_dir = os.path.join(self.TEST_ROOT, short_id)
426
358
        os.mkdir(self.test_dir)
427
359
        os.chdir(self.test_dir)
428
 
        super(TestCaseInTempDir, self).setUp()
429
360
        
430
361
    def tearDown(self):
431
362
        os.chdir(self._currentdir)
449
380
                print >>f, "contents of", name
450
381
                f.close()
451
382
 
452
 
    def build_tree_contents(self, shape):
453
 
        bzrlib.selftest.build_tree_contents(shape)
454
 
 
455
383
    def failUnlessExists(self, path):
456
384
        """Fail unless path, which may be abs or relative, exists."""
457
 
        self.failUnless(osutils.lexists(path))
458
 
        
459
 
    def assertFileEqual(self, content, path):
460
 
        """Fail if path does not contain 'content'."""
461
 
        self.failUnless(osutils.lexists(path))
462
 
        self.assertEqualDiff(content, open(path, 'r').read())
 
385
        self.failUnless(os.path.exists(path))
463
386
        
464
387
 
465
388
class MetaTestLog(TestCase):
468
391
        logging.info('an info message')
469
392
        warning('something looks dodgy...')
470
393
        logging.debug('hello, test is running')
471
 
        ## assert 0
 
394
        ##assert 0
472
395
 
473
396
 
474
397
def filter_suite_by_re(suite, pattern):
475
398
    result = TestUtil.TestSuite()
476
399
    filter_re = re.compile(pattern)
477
400
    for test in iter_suite_tests(suite):
478
 
        if filter_re.search(test.id()):
 
401
        if filter_re.match(test.id()):
479
402
            result.addTest(test)
480
403
    return result
481
404
 
482
405
 
483
 
def run_suite(suite, name='test', verbose=False, pattern=".*",
484
 
              stop_on_failure=False):
 
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):
485
421
    TestCaseInTempDir._TEST_NAME = name
486
422
    if verbose:
487
423
        verbosity = 2
490
426
    runner = TextTestRunner(stream=sys.stdout,
491
427
                            descriptions=0,
492
428
                            verbosity=verbosity)
493
 
    runner.stop_on_failure=stop_on_failure
 
429
    if testnames:
 
430
        suite = filter_suite_by_names(suite, testnames)
494
431
    if pattern != '.*':
495
432
        suite = filter_suite_by_re(suite, pattern)
496
433
    result = runner.run(suite)
505
442
    return result.wasSuccessful()
506
443
 
507
444
 
508
 
def selftest(verbose=False, pattern=".*", stop_on_failure=True):
 
445
def selftest(verbose=False, pattern=".*", testnames=None):
509
446
    """Run the whole test suite under the enhanced runner"""
510
447
    return run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern,
511
 
                     stop_on_failure=stop_on_failure)
 
448
                     testnames=testnames)
512
449
 
513
450
 
514
451
def test_suite():
521
458
 
522
459
    testmod_names = \
523
460
                  ['bzrlib.selftest.MetaTestLog',
524
 
                   'bzrlib.selftest.testgpg',
525
461
                   'bzrlib.selftest.testidentitymap',
526
462
                   'bzrlib.selftest.testinv',
527
463
                   'bzrlib.selftest.test_ancestry',
528
464
                   'bzrlib.selftest.test_commit',
529
465
                   'bzrlib.selftest.test_commit_merge',
530
 
                   'bzrlib.selftest.testconfig',
531
466
                   'bzrlib.selftest.versioning',
532
467
                   'bzrlib.selftest.testmerge3',
533
468
                   'bzrlib.selftest.testmerge',
556
491
                   'bzrlib.selftest.testworkingtree',
557
492
                   'bzrlib.selftest.test_upgrade',
558
493
                   'bzrlib.selftest.test_conflicts',
559
 
                   'bzrlib.selftest.testtestament',
560
 
                   'bzrlib.selftest.testannotate',
561
 
                   'bzrlib.selftest.testrevprops',
562
 
                   'bzrlib.selftest.testoptions',
563
 
                   'bzrlib.selftest.testhttp',
564
 
                   'bzrlib.selftest.testnonascii',
565
494
                   ]
566
495
 
567
496
    for m in (bzrlib.store, bzrlib.inventory, bzrlib.branch,
568
 
              bzrlib.osutils, bzrlib.commands, bzrlib.merge3,
569
 
              bzrlib.errors,
570
 
              ):
 
497
              bzrlib.osutils, bzrlib.commands, bzrlib.merge3):
571
498
        if m not in MODULES_TO_DOCTEST:
572
499
            MODULES_TO_DOCTEST.append(m)
573
500