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