1
"""Test result object"""
7
from io import StringIO
10
from functools import wraps
16
def inner(self, *args, **kw):
17
if getattr(self, 'failfast', False):
19
return method(self, *args, **kw)
22
STDOUT_LINE = '\nStdout:\n%s'
23
STDERR_LINE = '\nStderr:\n%s'
26
class TestResult(object):
27
"""Holder for test result information.
29
Test results are automatically managed by the TestCase and TestSuite
30
classes, and do not need to be explicitly manipulated by writers of tests.
32
Each instance holds the total number of tests run, and collections of
33
failures and errors that occurred among those test runs. The collections
34
contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
35
formatted traceback of the error that occurred.
37
_previousTestClass = None
38
_testRunEntered = False
39
_moduleSetUpFailed = False
40
def __init__(self, stream=None, descriptions=None, verbosity=None):
46
self.expectedFailures = []
47
self.unexpectedSuccesses = []
48
self.shouldStop = False
50
self._stdout_buffer = None
51
self._stderr_buffer = None
52
self._original_stdout = sys.stdout
53
self._original_stderr = sys.stderr
54
self._mirrorOutput = False
56
def printErrors(self):
57
"Called by TestRunner after test run"
59
def startTest(self, test):
60
"Called when the given test is about to be run"
62
self._mirrorOutput = False
65
def _setupStdout(self):
67
if self._stderr_buffer is None:
68
self._stderr_buffer = StringIO()
69
self._stdout_buffer = StringIO()
70
sys.stdout = self._stdout_buffer
71
sys.stderr = self._stderr_buffer
73
def startTestRun(self):
74
"""Called once before any tests are executed.
76
See startTest for a method called before each test.
79
def stopTest(self, test):
80
"""Called when the given test has been run"""
82
self._mirrorOutput = False
84
def _restoreStdout(self):
86
if self._mirrorOutput:
87
output = sys.stdout.getvalue()
88
error = sys.stderr.getvalue()
90
if not output.endswith('\n'):
92
self._original_stdout.write(STDOUT_LINE % output)
94
if not error.endswith('\n'):
96
self._original_stderr.write(STDERR_LINE % error)
98
sys.stdout = self._original_stdout
99
sys.stderr = self._original_stderr
100
self._stdout_buffer.seek(0)
101
self._stdout_buffer.truncate()
102
self._stderr_buffer.seek(0)
103
self._stderr_buffer.truncate()
105
def stopTestRun(self):
106
"""Called once after all tests are executed.
108
See stopTest for a method called after each test.
112
def addError(self, test, err):
113
"""Called when an error has occurred. 'err' is a tuple of values as
114
returned by sys.exc_info().
116
self.errors.append((test, self._exc_info_to_string(err, test)))
117
self._mirrorOutput = True
120
def addFailure(self, test, err):
121
"""Called when an error has occurred. 'err' is a tuple of values as
122
returned by sys.exc_info()."""
123
self.failures.append((test, self._exc_info_to_string(err, test)))
124
self._mirrorOutput = True
126
def addSuccess(self, test):
127
"Called when a test has completed successfully"
130
def addSkip(self, test, reason):
131
"""Called when a test is skipped."""
132
self.skipped.append((test, reason))
134
def addExpectedFailure(self, test, err):
135
"""Called when an expected failure/error occured."""
136
self.expectedFailures.append(
137
(test, self._exc_info_to_string(err, test)))
140
def addUnexpectedSuccess(self, test):
141
"""Called when a test was expected to fail, but succeed."""
142
self.unexpectedSuccesses.append(test)
144
def wasSuccessful(self):
145
"Tells whether or not this result was a success"
146
return len(self.failures) == len(self.errors) == 0
149
"Indicates that the tests should be aborted"
150
self.shouldStop = True
152
def _exc_info_to_string(self, err, test):
153
"""Converts a sys.exc_info()-style tuple of values into a string."""
154
exctype, value, tb = err
155
# Skip test runner traceback levels
156
while tb and self._is_relevant_tb_level(tb):
159
if exctype is test.failureException:
160
# Skip assert*() traceback levels
161
length = self._count_relevant_tb_levels(tb)
162
msgLines = traceback.format_exception(exctype, value, tb, length)
164
msgLines = traceback.format_exception(exctype, value, tb)
167
output = sys.stdout.getvalue()
168
error = sys.stderr.getvalue()
170
if not output.endswith('\n'):
172
msgLines.append(STDOUT_LINE % output)
174
if not error.endswith('\n'):
176
msgLines.append(STDERR_LINE % error)
177
return ''.join(msgLines)
180
def _is_relevant_tb_level(self, tb):
181
return '__unittest' in tb.tb_frame.f_globals
183
def _count_relevant_tb_levels(self, tb):
185
while tb and not self._is_relevant_tb_level(tb):
191
return ("<%s run=%i errors=%i failures=%i>" %
192
(util.strclass(self.__class__), self.testsRun, len(self.errors),