~certify-web-dev/twisted/certify-trunk

« back to all changes in this revision

Viewing changes to twisted/trial/reporter.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-02-21 18:17:46 UTC
  • mfrom: (2.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20090221181746-jx37hyuf8ljaj524
Tags: 8.2.0-1ubuntu1
* Tigthen dependencies to 8.2.
* Build-depend on python-central (>= 0.6.11).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# -*- test-case-name: twisted.trial.test.test_reporter -*-
2
2
#
3
 
# Copyright (c) 2001-2007 Twisted Matrix Laboratories.
 
3
# Copyright (c) 2001-2008 Twisted Matrix Laboratories.
4
4
# See LICENSE for details.
5
5
#
6
 
# Maintainer: Jonathan Lange <jml@twistedmatrix.com>
 
6
# Maintainer: Jonathan Lange
7
7
 
8
8
"""
9
9
Defines classes that handle the results of tests.
13
13
import time
14
14
import warnings
15
15
 
 
16
from twisted.python.compat import set
16
17
from twisted.python import reflect, log
17
18
from twisted.python.components import proxyForInterface
18
19
from twisted.python.failure import Failure
81
82
        return error
82
83
 
83
84
    def startTest(self, test):
84
 
        """This must be called before the given test is commenced.
 
85
        """
 
86
        This must be called before the given test is commenced.
85
87
 
86
88
        @type test: L{pyunit.TestCase}
87
89
        """
89
91
        self._testStarted = self._getTime()
90
92
 
91
93
    def stopTest(self, test):
92
 
        """This must be called after the given test is completed.
 
94
        """
 
95
        This must be called after the given test is completed.
93
96
 
94
97
        @type test: L{pyunit.TestCase}
95
98
        """
97
100
        self._lastTime = self._getTime() - self._testStarted
98
101
 
99
102
    def addFailure(self, test, fail):
100
 
        """Report a failed assertion for the given test.
 
103
        """
 
104
        Report a failed assertion for the given test.
101
105
 
102
106
        @type test: L{pyunit.TestCase}
103
107
        @type fail: L{Failure} or L{tuple}
105
109
        self.failures.append((test, self._getFailure(fail)))
106
110
 
107
111
    def addError(self, test, error):
108
 
        """Report an error that occurred while running the given test.
 
112
        """
 
113
        Report an error that occurred while running the given test.
109
114
 
110
115
        @type test: L{pyunit.TestCase}
111
 
        @type fail: L{Failure} or L{tuple}
 
116
        @type error: L{Failure} or L{tuple}
112
117
        """
113
118
        self.errors.append((test, self._getFailure(error)))
114
119
 
293
298
class Reporter(TestResult):
294
299
    """
295
300
    A basic L{TestResult} with support for writing to a stream.
 
301
 
 
302
    @ivar _startTime: The time when the first test was started. It defaults to
 
303
        C{None}, which means that no test was actually launched.
 
304
    @type _startTime: C{float} or C{NoneType}
 
305
 
 
306
    @ivar _warningCache: A C{set} of tuples of warning message (file, line,
 
307
        text, category) which have already been written to the output stream
 
308
        during the currently executing test.  This is used to avoid writing
 
309
        duplicates of the same warning to the output stream.
 
310
    @type _warningCache: C{set}
 
311
 
 
312
    @ivar _publisher: The log publisher which will be observed for warning
 
313
        events.
 
314
    @type _publisher: L{LogPublisher} (or another type sufficiently similar)
296
315
    """
297
316
 
298
317
    implements(itrial.IReporter)
300
319
    _separator = '-' * 79
301
320
    _doubleSeparator = '=' * 79
302
321
 
303
 
    def __init__(self, stream=sys.stdout, tbformat='default', realtime=False):
 
322
    def __init__(self, stream=sys.stdout, tbformat='default', realtime=False,
 
323
                 publisher=None):
304
324
        super(Reporter, self).__init__()
305
325
        self._stream = SafeStream(stream)
306
326
        self.tbformat = tbformat
307
327
        self.realtime = realtime
308
 
        # The time when the first test was started.
309
328
        self._startTime = None
 
329
        self._warningCache = set()
 
330
 
 
331
        # Start observing log events so as to be able to report warnings.
 
332
        self._publisher = publisher
 
333
        if publisher is not None:
 
334
            publisher.addObserver(self._observeWarnings)
 
335
 
 
336
 
 
337
    def _observeWarnings(self, event):
 
338
        """
 
339
        Observe warning events and write them to C{self._stream}.
 
340
 
 
341
        This method is a log observer which will be registered with
 
342
        C{self._publisher.addObserver}.
 
343
 
 
344
        @param event: A C{dict} from the logging system.  If it has a
 
345
            C{'warning'} key, a logged warning will be extracted from it and
 
346
            possibly written to C{self.stream}.
 
347
        """
 
348
        if 'warning' in event:
 
349
            key = (event['filename'], event['lineno'],
 
350
                   event['category'].split('.')[-1],
 
351
                   str(event['warning']))
 
352
            if key not in self._warningCache:
 
353
                self._warningCache.add(key)
 
354
                self._stream.write('%s:%s: %s: %s\n' % key)
310
355
 
311
356
 
312
357
    def stream(self):
313
358
        warnings.warn("stream is deprecated in Twisted 8.0.",
314
 
                      category=DeprecationWarning, stacklevel=4)
 
359
                      category=DeprecationWarning, stacklevel=2)
315
360
        return self._stream
316
361
    stream = property(stream)
317
362
 
318
363
 
319
364
    def separator(self):
320
365
        warnings.warn("separator is deprecated in Twisted 8.0.",
321
 
                      category=DeprecationWarning, stacklevel=4)
 
366
                      category=DeprecationWarning, stacklevel=2)
322
367
        return self._separator
323
368
    separator = property(separator)
324
369
 
326
371
    def startTest(self, test):
327
372
        """
328
373
        Called when a test begins to run. Records the time when it was first
329
 
        called.
 
374
        called and resets the warning cache.
330
375
 
331
376
        @param test: L{ITestCase}
332
377
        """
333
378
        super(Reporter, self).startTest(test)
334
379
        if self._startTime is None:
335
 
            self._startTime = time.time()
 
380
            self._startTime = self._getTime()
 
381
        self._warningCache = set()
336
382
 
337
383
 
338
384
    def addFailure(self, test, fail):
581
627
        Expects that L{_printErrors}, L{_writeln}, L{_write}, L{_printSummary}
582
628
        and L{_separator} are all implemented.
583
629
        """
 
630
        if self._publisher is not None:
 
631
            self._publisher.removeObserver(self._observeWarnings)
584
632
        self._printErrors()
585
633
        self._writeln(self._separator)
586
634
        if self._startTime is not None:
611
659
        %(num_failures) %(num_skips)'
612
660
        """
613
661
        numTests = self.testsRun
614
 
        t = (self._startTime - self._getTime(), numTests, numTests,
 
662
        if self._startTime is not None:
 
663
            timing = self._getTime() - self._startTime
 
664
        else:
 
665
            timing = 0
 
666
        t = (timing, numTests, numTests,
615
667
             len(self.errors), len(self.failures), len(self.skips))
616
668
        self._writeln(' '.join(map(str, t)))
617
669
 
734
786
    def __init__(self, stream):
735
787
        self.stream = stream
736
788
 
737
 
    def supported(self):
 
789
    def supported(cls, stream=sys.stdout):
738
790
        """
739
791
        A class method that returns True if the current platform supports
740
792
        coloring terminal output using this method. Returns False otherwise.
741
793
        """
742
 
        # assuming stderr
743
 
        # isatty() returns False when SSHd into Win32 machine
744
 
        if 'CYGWIN' in os.environ:
745
 
            return True
746
 
        if not sys.stderr.isatty():
 
794
        if not stream.isatty():
747
795
            return False # auto color only on TTYs
748
796
        try:
749
797
            import curses
750
 
            curses.setupterm()
751
 
            return curses.tigetnum("colors") > 2
752
 
        except:
753
 
            # guess false in case of error
 
798
        except ImportError:
754
799
            return False
 
800
        else:
 
801
            try:
 
802
                try:
 
803
                    return curses.tigetnum("colors") > 2
 
804
                except curses.error:
 
805
                    curses.setupterm()
 
806
                    return curses.tigetnum("colors") > 2
 
807
            except:
 
808
                # guess false in case of error
 
809
                return False
755
810
    supported = classmethod(supported)
756
811
 
757
812
    def write(self, text, color):
789
844
            'white': red | green | blue | bold
790
845
            }
791
846
 
792
 
    def supported(self):
 
847
    def supported(cls, stream=sys.stdout):
793
848
        try:
794
849
            import win32console
795
850
            screenBuffer = win32console.GetStdHandle(
822
877
    def __init__(self, stream):
823
878
        self.stream = stream
824
879
 
825
 
    def supported(self):
 
880
    def supported(cls, stream=sys.stdout):
826
881
        return True
827
882
    supported = classmethod(supported)
828
883
 
850
905
    TODONE = 'red'
851
906
    SUCCESS = 'green'
852
907
 
853
 
    def __init__(self, stream=sys.stdout, tbformat='default', realtime=False):
854
 
        super(TreeReporter, self).__init__(stream, tbformat, realtime)
 
908
    def __init__(self, stream=sys.stdout, *args, **kwargs):
 
909
        super(TreeReporter, self).__init__(stream, *args, **kwargs)
855
910
        self._lastTest = []
856
911
        for colorizer in [_Win32Colorizer, _AnsiColorizer, _NullColorizer]:
857
 
            if colorizer.supported():
 
912
            if colorizer.supported(stream):
858
913
                self._colorizer = colorizer(stream)
859
914
                break
860
915