github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/third_party/stdlib/unittest_result.py (about)

     1  """Test result object"""
     2  
     3  import os
     4  import sys
     5  import traceback
     6  
     7  # from StringIO import StringIO
     8  import StringIO as _StringIO
     9  StringIO = _StringIO.StringIO
    10  
    11  # from . import util
    12  # from functools import wraps
    13  import unittest_util as util
    14  import functools
    15  wraps = functools.wraps
    16  
    17  __unittest = True
    18  
    19  def failfast(method):
    20      # @wraps(method)
    21      def inner(self, *args, **kw):
    22          if getattr(self, 'failfast', False):
    23              self.stop()
    24          return method(self, *args, **kw)
    25      inner = wraps(method)(inner)
    26      return inner
    27  
    28  STDOUT_LINE = '\nStdout:\n%s'
    29  STDERR_LINE = '\nStderr:\n%s'
    30  
    31  
    32  class TestResult(object):
    33      """Holder for test result information.
    34  
    35      Test results are automatically managed by the TestCase and TestSuite
    36      classes, and do not need to be explicitly manipulated by writers of tests.
    37  
    38      Each instance holds the total number of tests run, and collections of
    39      failures and errors that occurred among those test runs. The collections
    40      contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
    41      formatted traceback of the error that occurred.
    42      """
    43      _previousTestClass = None
    44      _testRunEntered = False
    45      _moduleSetUpFailed = False
    46      def __init__(self, stream=None, descriptions=None, verbosity=None):
    47          self.failfast = False
    48          self.failures = []
    49          self.errors = []
    50          self.testsRun = 0
    51          self.skipped = []
    52          self.expectedFailures = []
    53          self.unexpectedSuccesses = []
    54          self.shouldStop = False
    55          self.buffer = False
    56          self._stdout_buffer = None
    57          self._stderr_buffer = None
    58          self._original_stdout = sys.stdout
    59          self._original_stderr = sys.stderr
    60          self._mirrorOutput = False
    61  
    62      def printErrors(self):
    63          "Called by TestRunner after test run"
    64  
    65      def startTest(self, test):
    66          "Called when the given test is about to be run"
    67          self.testsRun += 1
    68          self._mirrorOutput = False
    69          self._setupStdout()
    70  
    71      def _setupStdout(self):
    72          if self.buffer:
    73              if self._stderr_buffer is None:
    74                  self._stderr_buffer = StringIO()
    75                  self._stdout_buffer = StringIO()
    76              sys.stdout = self._stdout_buffer
    77              sys.stderr = self._stderr_buffer
    78  
    79      def startTestRun(self):
    80          """Called once before any tests are executed.
    81  
    82          See startTest for a method called before each test.
    83          """
    84  
    85      def stopTest(self, test):
    86          """Called when the given test has been run"""
    87          self._restoreStdout()
    88          self._mirrorOutput = False
    89  
    90      def _restoreStdout(self):
    91          if self.buffer:
    92              if self._mirrorOutput:
    93                  output = sys.stdout.getvalue()
    94                  error = sys.stderr.getvalue()
    95                  if output:
    96                      if not output.endswith('\n'):
    97                          output += '\n'
    98                      self._original_stdout.write(STDOUT_LINE % output)
    99                  if error:
   100                      if not error.endswith('\n'):
   101                          error += '\n'
   102                      self._original_stderr.write(STDERR_LINE % error)
   103  
   104              sys.stdout = self._original_stdout
   105              sys.stderr = self._original_stderr
   106              self._stdout_buffer.seek(0)
   107              self._stdout_buffer.truncate()
   108              self._stderr_buffer.seek(0)
   109              self._stderr_buffer.truncate()
   110  
   111      def stopTestRun(self):
   112          """Called once after all tests are executed.
   113  
   114          See stopTest for a method called after each test.
   115          """
   116  
   117      # @failfast
   118      def addError(self, test, err):
   119          """Called when an error has occurred. 'err' is a tuple of values as
   120          returned by sys.exc_info().
   121          """
   122          self.errors.append((test, self._exc_info_to_string(err, test)))
   123          self._mirrorOutput = True
   124      addError = failfast(addError)
   125  
   126      # @failfast
   127      def addFailure(self, test, err):
   128          """Called when an error has occurred. 'err' is a tuple of values as
   129          returned by sys.exc_info()."""
   130          self.failures.append((test, self._exc_info_to_string(err, test)))
   131          self._mirrorOutput = True
   132      addFailure = failfast(addFailure)
   133  
   134      def addSuccess(self, test):
   135          "Called when a test has completed successfully"
   136          pass
   137  
   138      def addSkip(self, test, reason):
   139          """Called when a test is skipped."""
   140          self.skipped.append((test, reason))
   141  
   142      def addExpectedFailure(self, test, err):
   143          """Called when an expected failure/error occurred."""
   144          self.expectedFailures.append(
   145              (test, self._exc_info_to_string(err, test)))
   146  
   147      # @failfast
   148      def addUnexpectedSuccess(self, test):
   149          """Called when a test was expected to fail, but succeed."""
   150          self.unexpectedSuccesses.append(test)
   151      addUnexpectedSuccess = failfast(addUnexpectedSuccess)
   152  
   153      def wasSuccessful(self):
   154          "Tells whether or not this result was a success"
   155          return len(self.failures) == len(self.errors) == 0
   156  
   157      def stop(self):
   158          "Indicates that the tests should be aborted"
   159          self.shouldStop = True
   160  
   161      def _exc_info_to_string(self, err, test):
   162          """Converts a sys.exc_info()-style tuple of values into a string."""
   163          exctype, value, tb = err
   164          # Skip test runner traceback levels
   165          while tb and self._is_relevant_tb_level(tb):
   166              tb = tb.tb_next
   167  
   168          if exctype is test.failureException:
   169              # Skip assert*() traceback levels
   170              length = self._count_relevant_tb_levels(tb)
   171              msgLines = traceback.format_exception(exctype, value, tb, length)
   172          else:
   173              msgLines = traceback.format_exception(exctype, value, tb)
   174  
   175          if self.buffer:
   176              output = sys.stdout.getvalue()
   177              error = sys.stderr.getvalue()
   178              if output:
   179                  if not output.endswith('\n'):
   180                      output += '\n'
   181                  msgLines.append(STDOUT_LINE % output)
   182              if error:
   183                  if not error.endswith('\n'):
   184                      error += '\n'
   185                  msgLines.append(STDERR_LINE % error)
   186          return ''.join(msgLines)
   187  
   188  
   189      def _is_relevant_tb_level(self, tb):
   190          return '__unittest' in tb.tb_frame.f_globals
   191  
   192      def _count_relevant_tb_levels(self, tb):
   193          length = 0
   194          while tb and not self._is_relevant_tb_level(tb):
   195              length += 1
   196              tb = tb.tb_next
   197          return length
   198  
   199      def __repr__(self):
   200          return ("<%s run=%i errors=%i failures=%i>" %
   201                 (util.strclass(self.__class__), self.testsRun, len(self.errors),
   202                  len(self.failures)))