+++ /dev/null
-"""Test result object"""\r
-\r
-import os\r
-import sys\r
-import traceback\r
-\r
-from StringIO import StringIO\r
-\r
-from . import util\r
-from functools import wraps\r
-\r
-__unittest = True\r
-\r
-def failfast(method):\r
- @wraps(method)\r
- def inner(self, *args, **kw):\r
- if getattr(self, 'failfast', False):\r
- self.stop()\r
- return method(self, *args, **kw)\r
- return inner\r
-\r
-STDOUT_LINE = '\nStdout:\n%s'\r
-STDERR_LINE = '\nStderr:\n%s'\r
-\r
-\r
-class TestResult(object):\r
- """Holder for test result information.\r
-\r
- Test results are automatically managed by the TestCase and TestSuite\r
- classes, and do not need to be explicitly manipulated by writers of tests.\r
-\r
- Each instance holds the total number of tests run, and collections of\r
- failures and errors that occurred among those test runs. The collections\r
- contain tuples of (testcase, exceptioninfo), where exceptioninfo is the\r
- formatted traceback of the error that occurred.\r
- """\r
- _previousTestClass = None\r
- _testRunEntered = False\r
- _moduleSetUpFailed = False\r
- def __init__(self, stream=None, descriptions=None, verbosity=None):\r
- self.failfast = False\r
- self.failures = []\r
- self.errors = []\r
- self.testsRun = 0\r
- self.skipped = []\r
- self.expectedFailures = []\r
- self.unexpectedSuccesses = []\r
- self.shouldStop = False\r
- self.buffer = False\r
- self._stdout_buffer = None\r
- self._stderr_buffer = None\r
- self._original_stdout = sys.stdout\r
- self._original_stderr = sys.stderr\r
- self._mirrorOutput = False\r
-\r
- def printErrors(self):\r
- "Called by TestRunner after test run"\r
-\r
- def startTest(self, test):\r
- "Called when the given test is about to be run"\r
- self.testsRun += 1\r
- self._mirrorOutput = False\r
- self._setupStdout()\r
-\r
- def _setupStdout(self):\r
- if self.buffer:\r
- if self._stderr_buffer is None:\r
- self._stderr_buffer = StringIO()\r
- self._stdout_buffer = StringIO()\r
- sys.stdout = self._stdout_buffer\r
- sys.stderr = self._stderr_buffer\r
-\r
- def startTestRun(self):\r
- """Called once before any tests are executed.\r
-\r
- See startTest for a method called before each test.\r
- """\r
-\r
- def stopTest(self, test):\r
- """Called when the given test has been run"""\r
- self._restoreStdout()\r
- self._mirrorOutput = False\r
-\r
- def _restoreStdout(self):\r
- if self.buffer:\r
- if self._mirrorOutput:\r
- output = sys.stdout.getvalue()\r
- error = sys.stderr.getvalue()\r
- if output:\r
- if not output.endswith('\n'):\r
- output += '\n'\r
- self._original_stdout.write(STDOUT_LINE % output)\r
- if error:\r
- if not error.endswith('\n'):\r
- error += '\n'\r
- self._original_stderr.write(STDERR_LINE % error)\r
-\r
- sys.stdout = self._original_stdout\r
- sys.stderr = self._original_stderr\r
- self._stdout_buffer.seek(0)\r
- self._stdout_buffer.truncate()\r
- self._stderr_buffer.seek(0)\r
- self._stderr_buffer.truncate()\r
-\r
- def stopTestRun(self):\r
- """Called once after all tests are executed.\r
-\r
- See stopTest for a method called after each test.\r
- """\r
-\r
- @failfast\r
- def addError(self, test, err):\r
- """Called when an error has occurred. 'err' is a tuple of values as\r
- returned by sys.exc_info().\r
- """\r
- self.errors.append((test, self._exc_info_to_string(err, test)))\r
- self._mirrorOutput = True\r
-\r
- @failfast\r
- def addFailure(self, test, err):\r
- """Called when an error has occurred. 'err' is a tuple of values as\r
- returned by sys.exc_info()."""\r
- self.failures.append((test, self._exc_info_to_string(err, test)))\r
- self._mirrorOutput = True\r
-\r
- def addSuccess(self, test):\r
- "Called when a test has completed successfully"\r
- pass\r
-\r
- def addSkip(self, test, reason):\r
- """Called when a test is skipped."""\r
- self.skipped.append((test, reason))\r
-\r
- def addExpectedFailure(self, test, err):\r
- """Called when an expected failure/error occured."""\r
- self.expectedFailures.append(\r
- (test, self._exc_info_to_string(err, test)))\r
-\r
- @failfast\r
- def addUnexpectedSuccess(self, test):\r
- """Called when a test was expected to fail, but succeed."""\r
- self.unexpectedSuccesses.append(test)\r
-\r
- def wasSuccessful(self):\r
- "Tells whether or not this result was a success"\r
- return len(self.failures) == len(self.errors) == 0\r
-\r
- def stop(self):\r
- "Indicates that the tests should be aborted"\r
- self.shouldStop = True\r
-\r
- def _exc_info_to_string(self, err, test):\r
- """Converts a sys.exc_info()-style tuple of values into a string."""\r
- exctype, value, tb = err\r
- # Skip test runner traceback levels\r
- while tb and self._is_relevant_tb_level(tb):\r
- tb = tb.tb_next\r
-\r
- if exctype is test.failureException:\r
- # Skip assert*() traceback levels\r
- length = self._count_relevant_tb_levels(tb)\r
- msgLines = traceback.format_exception(exctype, value, tb, length)\r
- else:\r
- msgLines = traceback.format_exception(exctype, value, tb)\r
-\r
- if self.buffer:\r
- output = sys.stdout.getvalue()\r
- error = sys.stderr.getvalue()\r
- if output:\r
- if not output.endswith('\n'):\r
- output += '\n'\r
- msgLines.append(STDOUT_LINE % output)\r
- if error:\r
- if not error.endswith('\n'):\r
- error += '\n'\r
- msgLines.append(STDERR_LINE % error)\r
- return ''.join(msgLines)\r
-\r
-\r
- def _is_relevant_tb_level(self, tb):\r
- return '__unittest' in tb.tb_frame.f_globals\r
-\r
- def _count_relevant_tb_levels(self, tb):\r
- length = 0\r
- while tb and not self._is_relevant_tb_level(tb):\r
- length += 1\r
- tb = tb.tb_next\r
- return length\r
-\r
- def __repr__(self):\r
- return ("<%s run=%i errors=%i failures=%i>" %\r
- (util.strclass(self.__class__), self.testsRun, len(self.errors),\r
- len(self.failures)))\r