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)))