annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/unittest/result.py @ 68:5028fdace37b

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