~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-08-25 05:04:05 UTC
  • mfrom: (4641.3.5 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20090825050405-9g097zqrev5ownl5
(robertc) Add --lsprof-tests option to bzr selftest for profiling
        individual tests. (Robert Collins)

Show diffs side-by-side

added added

removed removed

Lines of Context:
579
579
                 bench_history=None,
580
580
                 list_only=False,
581
581
                 strict=False,
 
582
                 result_decorators=None,
582
583
                 ):
 
584
        """Create a TextTestRunner.
 
585
 
 
586
        :param result_decorators: An optional list of decorators to apply
 
587
            to the result object being used by the runner. Decorators are
 
588
            applied left to right - the first element in the list is the 
 
589
            innermost decorator.
 
590
        """
583
591
        self.stream = unittest._WritelnDecorator(stream)
584
592
        self.descriptions = descriptions
585
593
        self.verbosity = verbosity
586
594
        self._bench_history = bench_history
587
595
        self.list_only = list_only
588
596
        self._strict = strict
 
597
        self._result_decorators = result_decorators or []
589
598
 
590
599
    def run(self, test):
591
600
        "Run the given test case or test suite."
600
609
                              bench_history=self._bench_history,
601
610
                              strict=self._strict,
602
611
                              )
 
612
        run_result = result
 
613
        for decorator in self._result_decorators:
 
614
            run_result = decorator(run_result)
603
615
        result.stop_early = self.stop_on_failure
604
616
        result.report_starting()
605
617
        if self.list_only:
614
626
            try:
615
627
                import testtools
616
628
            except ImportError:
617
 
                test.run(result)
 
629
                test.run(run_result)
618
630
            else:
619
631
                if isinstance(test, testtools.ConcurrentTestSuite):
620
632
                    # We need to catch bzr specific behaviors
621
 
                    test.run(BZRTransformingResult(result))
 
633
                    test.run(BZRTransformingResult(run_result))
622
634
                else:
623
 
                    test.run(result)
 
635
                    test.run(run_result)
624
636
            run = result.testsRun
625
637
            actionTaken = "Ran"
626
638
        stopTime = time.time()
2762
2774
              strict=False,
2763
2775
              runner_class=None,
2764
2776
              suite_decorators=None,
2765
 
              stream=None):
 
2777
              stream=None,
 
2778
              result_decorators=None,
 
2779
              ):
2766
2780
    """Run a test suite for bzr selftest.
2767
2781
 
2768
2782
    :param runner_class: The class of runner to use. Must support the
2785
2799
                            bench_history=bench_history,
2786
2800
                            list_only=list_only,
2787
2801
                            strict=strict,
 
2802
                            result_decorators=result_decorators,
2788
2803
                            )
2789
2804
    runner.stop_on_failure=stop_on_failure
2790
2805
    # built in decorator factories:
3131
3146
    return result
3132
3147
 
3133
3148
 
3134
 
class BZRTransformingResult(unittest.TestResult):
 
3149
class ForwardingResult(unittest.TestResult):
3135
3150
 
3136
3151
    def __init__(self, target):
3137
3152
        unittest.TestResult.__init__(self)
3143
3158
    def stopTest(self, test):
3144
3159
        self.result.stopTest(test)
3145
3160
 
 
3161
    def addSkip(self, test, reason):
 
3162
        self.result.addSkip(test, reason)
 
3163
 
 
3164
    def addSuccess(self, test):
 
3165
        self.result.addSuccess(test)
 
3166
 
 
3167
    def addError(self, test, err):
 
3168
        self.result.addError(test, err)
 
3169
 
 
3170
    def addFailure(self, test, err):
 
3171
        self.result.addFailure(test, err)
 
3172
 
 
3173
 
 
3174
class BZRTransformingResult(ForwardingResult):
 
3175
 
3146
3176
    def addError(self, test, err):
3147
3177
        feature = self._error_looks_like('UnavailableFeature: ', err)
3148
3178
        if feature is not None:
3158
3188
        else:
3159
3189
            self.result.addFailure(test, err)
3160
3190
 
3161
 
    def addSkip(self, test, reason):
3162
 
        self.result.addSkip(test, reason)
3163
 
 
3164
 
    def addSuccess(self, test):
3165
 
        self.result.addSuccess(test)
3166
 
 
3167
3191
    def _error_looks_like(self, prefix, err):
3168
3192
        """Deserialize exception and returns the stringify value."""
3169
3193
        import subunit
3181
3205
        return value
3182
3206
 
3183
3207
 
 
3208
class ProfileResult(ForwardingResult):
 
3209
    """Generate profiling data for all activity between start and success.
 
3210
    
 
3211
    The profile data is appended to the test's _benchcalls attribute and can
 
3212
    be accessed by the forwarded-to TestResult.
 
3213
 
 
3214
    While it might be cleaner do accumulate this in stopTest, addSuccess is
 
3215
    where our existing output support for lsprof is, and this class aims to
 
3216
    fit in with that: while it could be moved it's not necessary to accomplish
 
3217
    test profiling, nor would it be dramatically cleaner.
 
3218
    """
 
3219
 
 
3220
    def startTest(self, test):
 
3221
        self.profiler = bzrlib.lsprof.BzrProfiler()
 
3222
        self.profiler.start()
 
3223
        ForwardingResult.startTest(self, test)
 
3224
 
 
3225
    def addSuccess(self, test):
 
3226
        stats = self.profiler.stop()
 
3227
        try:
 
3228
            calls = test._benchcalls
 
3229
        except AttributeError:
 
3230
            test._benchcalls = []
 
3231
            calls = test._benchcalls
 
3232
        calls.append(((test.id(), "", ""), stats))
 
3233
        ForwardingResult.addSuccess(self, test)
 
3234
 
 
3235
    def stopTest(self, test):
 
3236
        ForwardingResult.stopTest(self, test)
 
3237
        self.profiler = None
 
3238
 
 
3239
 
3184
3240
# Controlled by "bzr selftest -E=..." option
3185
3241
# Currently supported:
3186
3242
#   -Eallow_debug           Will no longer clear debug.debug_flags() so it
3208
3264
             runner_class=None,
3209
3265
             suite_decorators=None,
3210
3266
             stream=None,
 
3267
             lsprof_tests=False,
3211
3268
             ):
3212
3269
    """Run the whole test suite under the enhanced runner"""
3213
3270
    # XXX: Very ugly way to do this...
3242
3299
        if starting_with:
3243
3300
            # But always filter as requested.
3244
3301
            suite = filter_suite_by_id_startswith(suite, starting_with)
 
3302
        result_decorators = []
 
3303
        if lsprof_tests:
 
3304
            result_decorators.append(ProfileResult)
3245
3305
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
3246
3306
                     stop_on_failure=stop_on_failure,
3247
3307
                     transport=transport,
3255
3315
                     runner_class=runner_class,
3256
3316
                     suite_decorators=suite_decorators,
3257
3317
                     stream=stream,
 
3318
                     result_decorators=result_decorators,
3258
3319
                     )
3259
3320
    finally:
3260
3321
        default_transport = old_transport