14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"""Test result object""" 24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport os 44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport sys 54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport traceback 64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom StringIO import StringIO 84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom . import util 104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom functools import wraps 114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm__unittest = True 134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef failfast(method): 154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @wraps(method) 164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def inner(self, *args, **kw): 174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if getattr(self, 'failfast', False): 184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.stop() 194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return method(self, *args, **kw) 204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return inner 214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSTDOUT_LINE = '\nStdout:\n%s' 234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmSTDERR_LINE = '\nStderr:\n%s' 244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass TestResult(object): 274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Holder for test result information. 284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Test results are automatically managed by the TestCase and TestSuite 304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm classes, and do not need to be explicitly manipulated by writers of tests. 314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Each instance holds the total number of tests run, and collections of 334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm failures and errors that occurred among those test runs. The collections 344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm contain tuples of (testcase, exceptioninfo), where exceptioninfo is the 354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm formatted traceback of the error that occurred. 364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _previousTestClass = None 384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _testRunEntered = False 394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _moduleSetUpFailed = False 404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __init__(self, stream=None, descriptions=None, verbosity=None): 414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.failfast = False 424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.failures = [] 434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.errors = [] 444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.testsRun = 0 454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.skipped = [] 464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.expectedFailures = [] 474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.unexpectedSuccesses = [] 484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.shouldStop = False 494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buffer = False 504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._stdout_buffer = None 514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._stderr_buffer = None 524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._original_stdout = sys.stdout 534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._original_stderr = sys.stderr 544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._mirrorOutput = False 554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def printErrors(self): 574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Called by TestRunner after test run" 584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def startTest(self, test): 604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Called when the given test is about to be run" 614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.testsRun += 1 624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._mirrorOutput = False 634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._setupStdout() 644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _setupStdout(self): 664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if self.buffer: 674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if self._stderr_buffer is None: 684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._stderr_buffer = StringIO() 694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._stdout_buffer = StringIO() 704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sys.stdout = self._stdout_buffer 714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sys.stderr = self._stderr_buffer 724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def startTestRun(self): 744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Called once before any tests are executed. 754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm See startTest for a method called before each test. 774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def stopTest(self, test): 804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Called when the given test has been run""" 814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._restoreStdout() 824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._mirrorOutput = False 834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _restoreStdout(self): 854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if self.buffer: 864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if self._mirrorOutput: 874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm output = sys.stdout.getvalue() 884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm error = sys.stderr.getvalue() 894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if output: 904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not output.endswith('\n'): 914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm output += '\n' 924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._original_stdout.write(STDOUT_LINE % output) 934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if error: 944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not error.endswith('\n'): 954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm error += '\n' 964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._original_stderr.write(STDERR_LINE % error) 974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sys.stdout = self._original_stdout 994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sys.stderr = self._original_stderr 1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._stdout_buffer.seek(0) 1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._stdout_buffer.truncate() 1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._stderr_buffer.seek(0) 1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._stderr_buffer.truncate() 1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def stopTestRun(self): 1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Called once after all tests are executed. 1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm See stopTest for a method called after each test. 1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @failfast 1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def addError(self, test, err): 1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Called when an error has occurred. 'err' is a tuple of values as 1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm returned by sys.exc_info(). 1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.errors.append((test, self._exc_info_to_string(err, test))) 1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._mirrorOutput = True 1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @failfast 1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def addFailure(self, test, err): 1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Called when an error has occurred. 'err' is a tuple of values as 1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm returned by sys.exc_info().""" 1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.failures.append((test, self._exc_info_to_string(err, test))) 1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._mirrorOutput = True 1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def addSuccess(self, test): 1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Called when a test has completed successfully" 1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def addSkip(self, test, reason): 1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Called when a test is skipped.""" 1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.skipped.append((test, reason)) 1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def addExpectedFailure(self, test, err): 1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Called when an expected failure/error occured.""" 1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.expectedFailures.append( 1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (test, self._exc_info_to_string(err, test))) 1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @failfast 1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def addUnexpectedSuccess(self, test): 1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Called when a test was expected to fail, but succeed.""" 1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.unexpectedSuccesses.append(test) 1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def wasSuccessful(self): 1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Tells whether or not this result was a success" 1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return len(self.failures) == len(self.errors) == 0 1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def stop(self): 1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Indicates that the tests should be aborted" 1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.shouldStop = True 1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _exc_info_to_string(self, err, test): 1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Converts a sys.exc_info()-style tuple of values into a string.""" 1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm exctype, value, tb = err 1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Skip test runner traceback levels 1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while tb and self._is_relevant_tb_level(tb): 1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm tb = tb.tb_next 1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if exctype is test.failureException: 1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Skip assert*() traceback levels 1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm length = self._count_relevant_tb_levels(tb) 1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msgLines = traceback.format_exception(exctype, value, tb, length) 1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msgLines = traceback.format_exception(exctype, value, tb) 1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if self.buffer: 1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm output = sys.stdout.getvalue() 1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm error = sys.stderr.getvalue() 1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if output: 1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not output.endswith('\n'): 1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm output += '\n' 1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msgLines.append(STDOUT_LINE % output) 1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if error: 1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not error.endswith('\n'): 1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm error += '\n' 1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm msgLines.append(STDERR_LINE % error) 1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return ''.join(msgLines) 1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _is_relevant_tb_level(self, tb): 1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return '__unittest' in tb.tb_frame.f_globals 1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _count_relevant_tb_levels(self, tb): 1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm length = 0 1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while tb and not self._is_relevant_tb_level(tb): 1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm length += 1 1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm tb = tb.tb_next 1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return length 1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __repr__(self): 1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return ("<%s run=%i errors=%i failures=%i>" % 1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (util.strclass(self.__class__), self.testsRun, len(self.errors), 1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm len(self.failures))) 194