175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen"""Test result object"""
275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenimport sys
475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenimport traceback
575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenimport unittest
675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenfrom StringIO import StringIO
875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenfrom unittest2 import util
1075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenfrom unittest2.compatibility import wraps
1175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
1275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen__unittest = True
1375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
1475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chendef failfast(method):
1575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    @wraps(method)
1675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def inner(self, *args, **kw):
1775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if getattr(self, 'failfast', False):
1875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self.stop()
1975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        return method(self, *args, **kw)
2075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    return inner
2175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
2275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
2375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenSTDOUT_LINE = '\nStdout:\n%s'
2475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny ChenSTDERR_LINE = '\nStderr:\n%s'
2575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
2675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chenclass TestResult(unittest.TestResult):
2775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    """Holder for test result information.
2875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
2975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    Test results are automatically managed by the TestCase and TestSuite
3075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    classes, and do not need to be explicitly manipulated by writers of tests.
3175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
3275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    Each instance holds the total number of tests run, and collections of
3375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    failures and errors that occurred among those test runs. The collections
3475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
3575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    formatted traceback of the error that occurred.
3675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    """
3775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    _previousTestClass = None
3875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    _moduleSetUpFailed = False
3975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
4075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def __init__(self):
4175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.failfast = False
4275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.failures = []
4375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.errors = []
4475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.testsRun = 0
4575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.skipped = []
4675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.expectedFailures = []
4775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.unexpectedSuccesses = []
4875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.shouldStop = False
4975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.buffer = False
5075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self._stdout_buffer = None
5175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self._stderr_buffer = None
5275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self._original_stdout = sys.stdout
5375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self._original_stderr = sys.stderr
5475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self._mirrorOutput = False
5575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
5675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def startTest(self, test):
5775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        "Called when the given test is about to be run"
5875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.testsRun += 1
5975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self._mirrorOutput = False
6075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.buffer:
6175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            if self._stderr_buffer is None:
6275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                self._stderr_buffer = StringIO()
6375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                self._stdout_buffer = StringIO()
6475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            sys.stdout = self._stdout_buffer
6575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            sys.stderr = self._stderr_buffer
6675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
6775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def startTestRun(self):
6875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        """Called once before any tests are executed.
6975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
7075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        See startTest for a method called before each test.
7175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        """
7275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
7375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def stopTest(self, test):
7475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        """Called when the given test has been run"""
7575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.buffer:
7675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            if self._mirrorOutput:
7775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                output = sys.stdout.getvalue()
7875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                error = sys.stderr.getvalue()
7975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                if output:
8075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    if not output.endswith('\n'):
8175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                        output += '\n'
8275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    self._original_stdout.write(STDOUT_LINE % output)
8375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                if error:
8475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    if not error.endswith('\n'):
8575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                        error += '\n'
8675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    self._original_stderr.write(STDERR_LINE % error)
8775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
8875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            sys.stdout = self._original_stdout
8975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            sys.stderr = self._original_stderr
9075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self._stdout_buffer.seek(0)
9175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self._stdout_buffer.truncate()
9275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self._stderr_buffer.seek(0)
9375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            self._stderr_buffer.truncate()
9475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self._mirrorOutput = False
9575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
9675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
9775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def stopTestRun(self):
9875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        """Called once after all tests are executed.
9975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
10075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        See stopTest for a method called after each test.
10175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        """
10275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
10375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    @failfast
10475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def addError(self, test, err):
10575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        """Called when an error has occurred. 'err' is a tuple of values as
10675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        returned by sys.exc_info().
10775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        """
10875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.errors.append((test, self._exc_info_to_string(err, test)))
10975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self._mirrorOutput = True
11075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
11175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    @failfast
11275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def addFailure(self, test, err):
11375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        """Called when an error has occurred. 'err' is a tuple of values as
11475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        returned by sys.exc_info()."""
11575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.failures.append((test, self._exc_info_to_string(err, test)))
11675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self._mirrorOutput = True
11775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
11875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def addSuccess(self, test):
11975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        "Called when a test has completed successfully"
12075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        pass
12175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
12275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def addSkip(self, test, reason):
12375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        """Called when a test is skipped."""
12475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.skipped.append((test, reason))
12575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
12621416a1d09aad1e25401e54578c3343bb0f0c25fEnrico Granata    def addExpectedFailure(self, test, err, bugnumber):
12775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        """Called when an expected failure/error occured."""
12875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.expectedFailures.append(
12975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            (test, self._exc_info_to_string(err, test)))
13075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
13175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    @failfast
13221416a1d09aad1e25401e54578c3343bb0f0c25fEnrico Granata    def addUnexpectedSuccess(self, test, bugnumber):
13375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        """Called when a test was expected to fail, but succeed."""
13475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.unexpectedSuccesses.append(test)
13575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
13675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def wasSuccessful(self):
13775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        "Tells whether or not this result was a success"
13875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        return (len(self.failures) + len(self.errors) == 0)
13975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
14075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def stop(self):
14175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        "Indicates that the tests should be aborted"
14275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        self.shouldStop = True
14375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
14475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def _exc_info_to_string(self, err, test):
14575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        """Converts a sys.exc_info()-style tuple of values into a string."""
14675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        exctype, value, tb = err
14775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        # Skip test runner traceback levels
14875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        while tb and self._is_relevant_tb_level(tb):
14975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            tb = tb.tb_next
15075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if exctype is test.failureException:
15175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            # Skip assert*() traceback levels
15275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            length = self._count_relevant_tb_levels(tb)
15375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            msgLines = traceback.format_exception(exctype, value, tb, length)
15475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        else:
15575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            msgLines = traceback.format_exception(exctype, value, tb)
15675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
15775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        if self.buffer:
15875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            output = sys.stdout.getvalue()
15975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            error = sys.stderr.getvalue()
16075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            if output:
16175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                if not output.endswith('\n'):
16275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    output += '\n'
16375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                msgLines.append(STDOUT_LINE % output)
16475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            if error:
16575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                if not error.endswith('\n'):
16675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                    error += '\n'
16775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                msgLines.append(STDERR_LINE % error)
16875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        return ''.join(msgLines)
16975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
17075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def _is_relevant_tb_level(self, tb):
17175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        return '__unittest' in tb.tb_frame.f_globals
17275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
17375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def _count_relevant_tb_levels(self, tb):
17475e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        length = 0
17575e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        while tb and not self._is_relevant_tb_level(tb):
17675e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            length += 1
17775e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen            tb = tb.tb_next
17875e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        return length
17975e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen
18075e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen    def __repr__(self):
18175e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen        return "<%s run=%i errors=%i failures=%i>" % \
18275e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen               (util.strclass(self.__class__), self.testsRun, len(self.errors),
18375e28f942c1b9f9c6d5a0d5f2efd037cbbc9fc74Johnny Chen                len(self.failures))
184