/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: v.ladeuil+lp at free
  • Date: 2006-11-08 07:44:30 UTC
  • mfrom: (2123 +trunk)
  • mto: (2145.1.1 keepalive)
  • mto: This revision was merged to the branch mainline in revision 2146.
  • Revision ID: v.ladeuil+lp@free.fr-20061108074430-a9c08d4a475bd97f
Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
import time
44
44
 
45
45
 
46
 
from bzrlib import memorytree
 
46
from bzrlib import (
 
47
    bzrdir,
 
48
    debug,
 
49
    errors,
 
50
    memorytree,
 
51
    osutils,
 
52
    progress,
 
53
    urlutils,
 
54
    )
47
55
import bzrlib.branch
48
 
import bzrlib.bzrdir as bzrdir
49
56
import bzrlib.commands
50
57
import bzrlib.bundle.serializer
51
 
import bzrlib.errors as errors
52
58
import bzrlib.export
53
59
import bzrlib.inventory
54
60
import bzrlib.iterablefile
61
67
from bzrlib.merge import merge_inner
62
68
import bzrlib.merge3
63
69
import bzrlib.osutils
64
 
import bzrlib.osutils as osutils
65
70
import bzrlib.plugin
66
 
import bzrlib.progress as progress
67
71
from bzrlib.revision import common_ancestor
68
72
import bzrlib.store
69
73
from bzrlib import symbol_versioning
73
77
from bzrlib.transport.local import LocalURLServer
74
78
from bzrlib.transport.memory import MemoryServer
75
79
from bzrlib.transport.readonly import ReadonlyServer
76
 
from bzrlib.trace import mutter
 
80
from bzrlib.trace import mutter, note
77
81
from bzrlib.tests import TestUtil
78
82
from bzrlib.tests.HttpServer import HttpServer
79
83
from bzrlib.tests.TestUtil import (
81
85
                          TestLoader,
82
86
                          )
83
87
from bzrlib.tests.treeshape import build_tree_contents
84
 
import bzrlib.urlutils as urlutils
85
88
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
86
89
 
87
90
default_transport = LocalURLServer
132
135
            ]
133
136
 
134
137
 
135
 
class _MyResult(unittest._TextTestResult):
136
 
    """Custom TestResult.
 
138
class ExtendedTestResult(unittest._TextTestResult):
 
139
    """Accepts, reports and accumulates the results of running tests.
137
140
 
138
 
    Shows output in a different format, including displaying runtime for tests.
 
141
    Compared to this unittest version this class adds support for profiling,
 
142
    benchmarking, stopping as soon as a test fails,  and skipping tests.
 
143
    There are further-specialized subclasses for different types of display.
139
144
    """
 
145
 
140
146
    stop_early = False
141
147
    
142
 
    def __init__(self, stream, descriptions, verbosity, pb=None,
143
 
                 bench_history=None):
 
148
    def __init__(self, stream, descriptions, verbosity,
 
149
                 bench_history=None,
 
150
                 num_tests=None,
 
151
                 ):
144
152
        """Construct new TestResult.
145
153
 
146
154
        :param bench_history: Optionally, a writable file object to accumulate
147
155
            benchmark results.
148
156
        """
149
157
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
150
 
        self.pb = pb
151
158
        if bench_history is not None:
152
159
            from bzrlib.version import _get_bzr_source_tree
153
160
            src_tree = _get_bzr_source_tree()
163
170
                revision_id = ''
164
171
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
165
172
        self._bench_history = bench_history
 
173
        self.ui = bzrlib.ui.ui_factory
 
174
        self.num_tests = num_tests
 
175
        self.error_count = 0
 
176
        self.failure_count = 0
 
177
        self.skip_count = 0
 
178
        self.count = 0
 
179
        self._overall_start_time = time.time()
166
180
    
167
181
    def extractBenchmarkTime(self, testCase):
168
182
        """Add a benchmark time for the current test case."""
184
198
        """Format seconds as milliseconds with leading spaces."""
185
199
        return "%5dms" % (1000 * seconds)
186
200
 
187
 
    def _ellipsise_unimportant_words(self, a_string, final_width,
188
 
                                   keep_start=False):
189
 
        """Add ellipses (sp?) for overly long strings.
190
 
        
191
 
        :param keep_start: If true preserve the start of a_string rather
192
 
                           than the end of it.
193
 
        """
194
 
        if keep_start:
195
 
            if len(a_string) > final_width:
196
 
                result = a_string[:final_width-3] + '...'
197
 
            else:
198
 
                result = a_string
199
 
        else:
200
 
            if len(a_string) > final_width:
201
 
                result = '...' + a_string[3-final_width:]
202
 
            else:
203
 
                result = a_string
204
 
        return result.ljust(final_width)
 
201
    def _shortened_test_description(self, test):
 
202
        what = test.id()
 
203
        what = re.sub(r'^bzrlib\.(tests|benchmark)\.', '', what)
 
204
        return what
205
205
 
206
206
    def startTest(self, test):
207
207
        unittest.TestResult.startTest(self, test)
208
 
        # In a short description, the important words are in
209
 
        # the beginning, but in an id, the important words are
210
 
        # at the end
211
 
        SHOW_DESCRIPTIONS = False
212
 
 
213
 
        if not self.showAll and self.dots and self.pb is not None:
214
 
            final_width = 13
215
 
        else:
216
 
            final_width = osutils.terminal_width()
217
 
            final_width = final_width - 15 - 8
218
 
        what = None
219
 
        if SHOW_DESCRIPTIONS:
220
 
            what = test.shortDescription()
221
 
            if what:
222
 
                what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
223
 
        if what is None:
224
 
            what = test.id()
225
 
            if what.startswith('bzrlib.tests.'):
226
 
                what = what[13:]
227
 
            what = self._ellipsise_unimportant_words(what, final_width)
228
 
        if self.showAll:
229
 
            self.stream.write(what)
230
 
        elif self.dots and self.pb is not None:
231
 
            self.pb.update(what, self.testsRun - 1, None)
232
 
        self.stream.flush()
 
208
        self.report_test_start(test)
233
209
        self._recordTestStartTime()
234
210
 
235
211
    def _recordTestStartTime(self):
246
222
        if setKeepLogfile is not None:
247
223
            setKeepLogfile()
248
224
        self.extractBenchmarkTime(test)
249
 
        if self.showAll:
250
 
            self.stream.writeln("ERROR %s" % self._testTimeString())
251
 
        elif self.dots and self.pb is None:
252
 
            self.stream.write('E')
253
 
        elif self.dots:
254
 
            self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
255
 
            self.pb.note(self._ellipsise_unimportant_words(
256
 
                            test.id() + ': ERROR',
257
 
                            osutils.terminal_width()))
258
 
        self.stream.flush()
 
225
        self.report_error(test, err)
259
226
        if self.stop_early:
260
227
            self.stop()
261
228
 
267
234
        if setKeepLogfile is not None:
268
235
            setKeepLogfile()
269
236
        self.extractBenchmarkTime(test)
270
 
        if self.showAll:
271
 
            self.stream.writeln(" FAIL %s" % self._testTimeString())
272
 
        elif self.dots and self.pb is None:
273
 
            self.stream.write('F')
274
 
        elif self.dots:
275
 
            self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
276
 
            self.pb.note(self._ellipsise_unimportant_words(
277
 
                            test.id() + ': FAIL',
278
 
                            osutils.terminal_width()))
279
 
        self.stream.flush()
 
237
        self.report_failure(test, err)
280
238
        if self.stop_early:
281
239
            self.stop()
282
240
 
287
245
                self._bench_history.write("%s %s\n" % (
288
246
                    self._formatTime(self._benchmarkTime),
289
247
                    test.id()))
290
 
        if self.showAll:
291
 
            self.stream.writeln('   OK %s' % self._testTimeString())
292
 
            for bench_called, stats in getattr(test, '_benchcalls', []):
293
 
                self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
294
 
                stats.pprint(file=self.stream)
295
 
        elif self.dots and self.pb is None:
296
 
            self.stream.write('~')
297
 
        elif self.dots:
298
 
            self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
299
 
        self.stream.flush()
 
248
        self.report_success(test)
300
249
        unittest.TestResult.addSuccess(self, test)
301
250
 
302
251
    def addSkipped(self, test, skip_excinfo):
303
252
        self.extractBenchmarkTime(test)
304
 
        if self.showAll:
305
 
            print >>self.stream, ' SKIP %s' % self._testTimeString()
306
 
            print >>self.stream, '     %s' % skip_excinfo[1]
307
 
        elif self.dots and self.pb is None:
308
 
            self.stream.write('S')
309
 
        elif self.dots:
310
 
            self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
311
 
        self.stream.flush()
 
253
        self.report_skip(test, skip_excinfo)
312
254
        # seems best to treat this as success from point-of-view of unittest
313
255
        # -- it actually does nothing so it barely matters :)
314
256
        try:
334
276
            self.stream.writeln(self.separator2)
335
277
            self.stream.writeln("%s" % err)
336
278
 
 
279
    def finished(self):
 
280
        pass
 
281
 
 
282
    def report_cleaning_up(self):
 
283
        pass
 
284
 
 
285
    def report_success(self, test):
 
286
        pass
 
287
 
 
288
 
 
289
class TextTestResult(ExtendedTestResult):
 
290
    """Displays progress and results of tests in text form"""
 
291
 
 
292
    def __init__(self, *args, **kw):
 
293
        ExtendedTestResult.__init__(self, *args, **kw)
 
294
        self.pb = self.ui.nested_progress_bar()
 
295
        self.pb.show_pct = False
 
296
        self.pb.show_spinner = False
 
297
        self.pb.show_eta = False, 
 
298
        self.pb.show_count = False
 
299
        self.pb.show_bar = False
 
300
 
 
301
    def report_starting(self):
 
302
        self.pb.update('[test 0/%d] starting...' % (self.num_tests))
 
303
 
 
304
    def _progress_prefix_text(self):
 
305
        a = '[%d' % self.count
 
306
        if self.num_tests is not None:
 
307
            a +='/%d' % self.num_tests
 
308
        a += ' in %ds' % (time.time() - self._overall_start_time)
 
309
        if self.error_count:
 
310
            a += ', %d errors' % self.error_count
 
311
        if self.failure_count:
 
312
            a += ', %d failed' % self.failure_count
 
313
        if self.skip_count:
 
314
            a += ', %d skipped' % self.skip_count
 
315
        a += ']'
 
316
        return a
 
317
 
 
318
    def report_test_start(self, test):
 
319
        self.count += 1
 
320
        self.pb.update(
 
321
                self._progress_prefix_text()
 
322
                + ' ' 
 
323
                + self._shortened_test_description(test))
 
324
 
 
325
    def report_error(self, test, err):
 
326
        self.error_count += 1
 
327
        self.pb.note('ERROR: %s\n    %s\n' % (
 
328
            self._shortened_test_description(test),
 
329
            err[1],
 
330
            ))
 
331
 
 
332
    def report_failure(self, test, err):
 
333
        self.failure_count += 1
 
334
        self.pb.note('FAIL: %s\n    %s\n' % (
 
335
            self._shortened_test_description(test),
 
336
            err[1],
 
337
            ))
 
338
 
 
339
    def report_skip(self, test, skip_excinfo):
 
340
        self.skip_count += 1
 
341
        if False:
 
342
            # at the moment these are mostly not things we can fix
 
343
            # and so they just produce stipple; use the verbose reporter
 
344
            # to see them.
 
345
            if False:
 
346
                # show test and reason for skip
 
347
                self.pb.note('SKIP: %s\n    %s\n' % (
 
348
                    self._shortened_test_description(test),
 
349
                    skip_excinfo[1]))
 
350
            else:
 
351
                # since the class name was left behind in the still-visible
 
352
                # progress bar...
 
353
                self.pb.note('SKIP: %s' % (skip_excinfo[1]))
 
354
 
 
355
    def report_cleaning_up(self):
 
356
        self.pb.update('cleaning up...')
 
357
 
 
358
    def finished(self):
 
359
        self.pb.finished()
 
360
 
 
361
 
 
362
class VerboseTestResult(ExtendedTestResult):
 
363
    """Produce long output, with one line per test run plus times"""
 
364
 
 
365
    def _ellipsize_to_right(self, a_string, final_width):
 
366
        """Truncate and pad a string, keeping the right hand side"""
 
367
        if len(a_string) > final_width:
 
368
            result = '...' + a_string[3-final_width:]
 
369
        else:
 
370
            result = a_string
 
371
        return result.ljust(final_width)
 
372
 
 
373
    def report_starting(self):
 
374
        self.stream.write('running %d tests...\n' % self.num_tests)
 
375
 
 
376
    def report_test_start(self, test):
 
377
        self.count += 1
 
378
        name = self._shortened_test_description(test)
 
379
        self.stream.write(self._ellipsize_to_right(name, 60))
 
380
        self.stream.flush()
 
381
 
 
382
    def report_error(self, test, err):
 
383
        self.error_count += 1
 
384
        self.stream.writeln('ERROR %s\n    %s' 
 
385
                % (self._testTimeString(), err[1]))
 
386
 
 
387
    def report_failure(self, test, err):
 
388
        self.failure_count += 1
 
389
        self.stream.writeln('FAIL %s\n    %s'
 
390
                % (self._testTimeString(), err[1]))
 
391
 
 
392
    def report_success(self, test):
 
393
        self.stream.writeln('   OK %s' % self._testTimeString())
 
394
        for bench_called, stats in getattr(test, '_benchcalls', []):
 
395
            self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
 
396
            stats.pprint(file=self.stream)
 
397
        self.stream.flush()
 
398
 
 
399
    def report_skip(self, test, skip_excinfo):
 
400
        print >>self.stream, ' SKIP %s' % self._testTimeString()
 
401
        print >>self.stream, '     %s' % skip_excinfo[1]
 
402
 
337
403
 
338
404
class TextTestRunner(object):
339
405
    stop_on_failure = False
343
409
                 descriptions=0,
344
410
                 verbosity=1,
345
411
                 keep_output=False,
346
 
                 pb=None,
347
412
                 bench_history=None):
348
413
        self.stream = unittest._WritelnDecorator(stream)
349
414
        self.descriptions = descriptions
350
415
        self.verbosity = verbosity
351
416
        self.keep_output = keep_output
352
 
        self.pb = pb
353
417
        self._bench_history = bench_history
354
418
 
355
 
    def _makeResult(self):
356
 
        result = _MyResult(self.stream,
357
 
                           self.descriptions,
358
 
                           self.verbosity,
359
 
                           pb=self.pb,
360
 
                           bench_history=self._bench_history)
361
 
        result.stop_early = self.stop_on_failure
362
 
        return result
363
 
 
364
419
    def run(self, test):
365
420
        "Run the given test case or test suite."
366
 
        result = self._makeResult()
367
421
        startTime = time.time()
368
 
        if self.pb is not None:
369
 
            self.pb.update('Running tests', 0, test.countTestCases())
 
422
        if self.verbosity == 1:
 
423
            result_class = TextTestResult
 
424
        elif self.verbosity >= 2:
 
425
            result_class = VerboseTestResult
 
426
        result = result_class(self.stream,
 
427
                              self.descriptions,
 
428
                              self.verbosity,
 
429
                              bench_history=self._bench_history,
 
430
                              num_tests=test.countTestCases(),
 
431
                              )
 
432
        result.stop_early = self.stop_on_failure
 
433
        result.report_starting()
370
434
        test.run(result)
371
435
        stopTime = time.time()
372
436
        timeTaken = stopTime - startTime
387
451
            self.stream.writeln(")")
388
452
        else:
389
453
            self.stream.writeln("OK")
390
 
        if self.pb is not None:
391
 
            self.pb.update('Cleaning up', 0, 1)
 
454
        result.report_cleaning_up()
392
455
        # This is still a little bogus, 
393
456
        # but only a little. Folk not using our testrunner will
394
457
        # have to delete their temp directories themselves.
409
472
                        sys.getfilesystemencoding())
410
473
                osutils.rmtree(test_root)
411
474
        else:
412
 
            if self.pb is not None:
413
 
                self.pb.note("Failed tests working directories are in '%s'\n",
414
 
                             test_root)
415
 
            else:
416
 
                self.stream.writeln(
417
 
                    "Failed tests working directories are in '%s'\n" %
418
 
                    test_root)
 
475
            note("Failed tests working directories are in '%s'\n", test_root)
419
476
        TestCaseWithMemoryTransport.TEST_ROOT = None
420
 
        if self.pb is not None:
421
 
            self.pb.clear()
 
477
        result.finished()
422
478
        return result
423
479
 
424
480
 
504
560
        unittest.TestCase.setUp(self)
505
561
        self._cleanEnvironment()
506
562
        bzrlib.trace.disable_default_logging()
 
563
        self._silenceUI()
507
564
        self._startLogFile()
508
565
        self._benchcalls = []
509
566
        self._benchtime = None
510
567
 
 
568
    def _silenceUI(self):
 
569
        """Turn off UI for duration of test"""
 
570
        # by default the UI is off; tests can turn it on if they want it.
 
571
        saved = bzrlib.ui.ui_factory
 
572
        def _restore():
 
573
            bzrlib.ui.ui_factory = saved
 
574
        bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
 
575
        self.addCleanup(_restore)
 
576
 
511
577
    def _ndiff_strings(self, a, b):
512
578
        """Return ndiff between two strings containing lines.
513
579
        
622
688
            a_callable(*args, **kwargs).
623
689
        """
624
690
        local_warnings = []
625
 
        def capture_warnings(msg, cls, stacklevel=None):
 
691
        def capture_warnings(msg, cls=None, stacklevel=None):
626
692
            # we've hooked into a deprecation specific callpath,
627
693
            # only deprecations should getting sent via it.
628
694
            self.assertEqual(cls, DeprecationWarning)
856
922
            os.chdir(working_dir)
857
923
 
858
924
        try:
859
 
            result = self.apply_redirected(stdin, stdout, stderr,
860
 
                                           bzrlib.commands.run_bzr_catch_errors,
861
 
                                           argv)
 
925
            saved_debug_flags = frozenset(debug.debug_flags)
 
926
            debug.debug_flags.clear()
 
927
            try:
 
928
                result = self.apply_redirected(stdin, stdout, stderr,
 
929
                                               bzrlib.commands.run_bzr_catch_errors,
 
930
                                               argv)
 
931
            finally:
 
932
                debug.debug_flags.update(saved_debug_flags)
862
933
        finally:
863
934
            logger.removeHandler(handler)
864
935
            bzrlib.ui.ui_factory = old_ui_factory
1579
1650
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
1580
1651
    if verbose:
1581
1652
        verbosity = 2
1582
 
        pb = None
1583
1653
    else:
1584
1654
        verbosity = 1
1585
 
        pb = progress.ProgressBar()
1586
1655
    runner = TextTestRunner(stream=sys.stdout,
1587
1656
                            descriptions=0,
1588
1657
                            verbosity=verbosity,
1589
1658
                            keep_output=keep_output,
1590
 
                            pb=pb,
1591
1659
                            bench_history=bench_history)
1592
1660
    runner.stop_on_failure=stop_on_failure
1593
1661
    if pattern != '.*':