Home | History | Annotate | Download | only in unittest2
      1 """Running tests"""
      2 
      3 import sys
      4 import time
      5 import unittest
      6 import progress
      7 
      8 from unittest2 import result
      9 
     10 try:
     11     from unittest2.signals import registerResult
     12 except ImportError:
     13     def registerResult(_):
     14         pass
     15     
     16 __unittest = True
     17 
     18 
     19 class _WritelnDecorator(object):
     20     """Used to decorate file-like objects with a handy 'writeln' method"""
     21     def __init__(self,stream):
     22         self.stream = stream
     23 
     24     def __getattr__(self, attr):
     25         if attr in ('stream', '__getstate__'):
     26             raise AttributeError(attr)
     27         return getattr(self.stream,attr)
     28 
     29     def writeln(self, arg=None):
     30         if arg:
     31             self.write(arg)
     32         self.write('\n') # text-mode streams translate to \r\n if needed
     33 
     34 
     35 class TextTestResult(result.TestResult):
     36     """A test result class that can print formatted text results to a stream.
     37 
     38     Used by TextTestRunner.
     39     """
     40     separator1 = '=' * 70
     41     separator2 = '-' * 70
     42 
     43     def __init__(self, stream, descriptions, verbosity):
     44         super(TextTestResult, self).__init__()
     45         self.stream = stream
     46         self.showAll = verbosity > 1
     47         self.dots = verbosity == 1
     48         self.descriptions = descriptions
     49         self.progressbar = None
     50 
     51     def getDescription(self, test):
     52         doc_first_line = test.shortDescription()
     53         if self.descriptions and doc_first_line:
     54             return '\n'.join((str(test), doc_first_line))
     55         else:
     56             return str(test)
     57 
     58     def startTest(self, test):
     59         super(TextTestResult, self).startTest(test)
     60         if self.showAll:
     61             self.stream.write(self.getDescription(test))
     62             self.stream.write(" ... ")
     63             self.stream.flush()
     64 
     65     def newTestResult(self,test,result_short,result_long):
     66         if self.showAll:
     67             self.stream.writeln(result_long)
     68         elif self.progressbar:
     69             self.progressbar.__add__(1)
     70             self.progressbar.add_event(result_short)
     71             self.progressbar.show_progress()
     72         elif self.dots:
     73             self.stream.write(result_short)
     74             self.stream.flush()
     75 
     76     def addSuccess(self, test):
     77         super(TextTestResult, self).addSuccess(test)
     78         if self.progressbar:
     79             self.newTestResult(test,"ok","ok")
     80         else:
     81             self.newTestResult(test,".","ok")
     82 
     83     def addError(self, test, err):
     84         super(TextTestResult, self).addError(test, err)
     85         self.newTestResult(test,"E","ERROR")
     86 
     87     def addFailure(self, test, err):
     88         super(TextTestResult, self).addFailure(test, err)
     89         self.newTestResult(test,"F","FAILURE")
     90 
     91     def addSkip(self, test, reason):
     92         super(TextTestResult, self).addSkip(test, reason)
     93         self.newTestResult(test,"s","skipped %r" % (reason,))
     94 
     95     def addExpectedFailure(self, test, err, bugnumber):
     96         super(TextTestResult, self).addExpectedFailure(test, err, bugnumber)
     97         self.newTestResult(test,"x","expected failure")
     98 
     99     def addUnexpectedSuccess(self, test, bugnumber):
    100         super(TextTestResult, self).addUnexpectedSuccess(test, bugnumber)
    101         self.newTestResult(test,"u","unexpected success")
    102 
    103     def printErrors(self):
    104         if self.progressbar:
    105             self.progressbar.complete()
    106             self.progressbar.show_progress()
    107         if self.dots or self.showAll:
    108             self.stream.writeln()
    109         self.printErrorList('ERROR', self.errors)
    110         self.printErrorList('FAIL', self.failures)
    111 
    112     def printErrorList(self, flavour, errors):
    113         for test, err in errors:
    114             self.stream.writeln(self.separator1)
    115             self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
    116             self.stream.writeln(self.separator2)
    117             self.stream.writeln("%s" % err)
    118 
    119     def stopTestRun(self):
    120         super(TextTestResult, self).stopTestRun()
    121         self.printErrors()
    122 
    123 
    124 class TextTestRunner(unittest.TextTestRunner):
    125     """A test runner class that displays results in textual form.
    126 
    127     It prints out the names of tests as they are run, errors as they
    128     occur, and a summary of the results at the end of the test run.
    129     """
    130     resultclass = TextTestResult
    131 
    132     def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1,
    133                     failfast=False, buffer=False, resultclass=None):
    134         self.stream = _WritelnDecorator(stream)
    135         self.descriptions = descriptions
    136         self.verbosity = verbosity
    137         self.failfast = failfast
    138         self.buffer = buffer
    139         if resultclass is not None:
    140             self.resultclass = resultclass
    141 
    142     def _makeResult(self):
    143         return self.resultclass(self.stream, self.descriptions, self.verbosity)
    144 
    145     def run(self, test):
    146         "Run the given test case or test suite."
    147         result = self._makeResult()
    148         result.failfast = self.failfast
    149         result.buffer = self.buffer
    150         registerResult(result)
    151         
    152         startTime = time.time()
    153         startTestRun = getattr(result, 'startTestRun', None)
    154         if startTestRun is not None:
    155             startTestRun()
    156         try:
    157             test(result)
    158         finally:
    159             stopTestRun = getattr(result, 'stopTestRun', None)
    160             if stopTestRun is not None:
    161                 stopTestRun()
    162             else:
    163                 result.printErrors()
    164         stopTime = time.time()
    165         timeTaken = stopTime - startTime
    166         if hasattr(result, 'separator2'):
    167             self.stream.writeln(result.separator2)
    168         run = result.testsRun
    169         self.stream.writeln("Ran %d test%s in %.3fs" %
    170                             (run, run != 1 and "s" or "", timeTaken))
    171         self.stream.writeln()
    172         
    173         expectedFails = unexpectedSuccesses = skipped = 0
    174         try:
    175             results = map(len, (result.expectedFailures,
    176                                 result.unexpectedSuccesses,
    177                                 result.skipped))
    178             expectedFails, unexpectedSuccesses, skipped = results
    179         except AttributeError:
    180             pass
    181         infos = []
    182         if not result.wasSuccessful():
    183             self.stream.write("FAILED")
    184             failed, errored = map(len, (result.failures, result.errors))
    185             if failed:
    186                 infos.append("failures=%d" % failed)
    187             if errored:
    188                 infos.append("errors=%d" % errored)
    189         else:
    190             self.stream.write("OK")
    191         if skipped:
    192             infos.append("skipped=%d" % skipped)
    193         if expectedFails:
    194             infos.append("expected failures=%d" % expectedFails)
    195         if unexpectedSuccesses:
    196             infos.append("unexpected successes=%d" % unexpectedSuccesses)
    197         if infos:
    198             self.stream.writeln(" (%s)" % (", ".join(infos),))
    199         else:
    200             self.stream.write("\n")
    201         return result
    202