| 1 | #!/usr/bin/env python
|
|---|
| 2 | '''
|
|---|
| 3 | Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
|
|---|
| 4 | Smalltalk testing framework.
|
|---|
| 5 |
|
|---|
| 6 | This module contains the core framework classes that form the basis of
|
|---|
| 7 | specific test cases and suites (TestCase, TestSuite etc.), and also a
|
|---|
| 8 | text-based utility class for running the tests and reporting the results
|
|---|
| 9 | (TextTestRunner).
|
|---|
| 10 |
|
|---|
| 11 | Simple usage:
|
|---|
| 12 |
|
|---|
| 13 | import unittest
|
|---|
| 14 |
|
|---|
| 15 | class IntegerArithmenticTestCase(unittest.TestCase):
|
|---|
| 16 | def testAdd(self): ## test method names begin 'test*'
|
|---|
| 17 | self.assertEquals((1 + 2), 3)
|
|---|
| 18 | self.assertEquals(0 + 1, 1)
|
|---|
| 19 | def testMultiply(self):
|
|---|
| 20 | self.assertEquals((0 * 10), 0)
|
|---|
| 21 | self.assertEquals((5 * 8), 40)
|
|---|
| 22 |
|
|---|
| 23 | if __name__ == '__main__':
|
|---|
| 24 | unittest.main()
|
|---|
| 25 |
|
|---|
| 26 | Further information is available in the bundled documentation, and from
|
|---|
| 27 |
|
|---|
| 28 | http://pyunit.sourceforge.net/
|
|---|
| 29 |
|
|---|
| 30 | Copyright (c) 1999-2003 Steve Purcell
|
|---|
| 31 | This module is free software, and you may redistribute it and/or modify
|
|---|
| 32 | it under the same terms as Python itself, so long as this copyright message
|
|---|
| 33 | and disclaimer are retained in their original form.
|
|---|
| 34 |
|
|---|
| 35 | IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
|---|
| 36 | SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
|
|---|
| 37 | THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
|---|
| 38 | DAMAGE.
|
|---|
| 39 |
|
|---|
| 40 | THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
|
|---|
| 41 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|---|
| 42 | PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
|
|---|
| 43 | AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
|
|---|
| 44 | SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
|---|
| 45 | '''
|
|---|
| 46 |
|
|---|
| 47 | __author__ = "Steve Purcell"
|
|---|
| 48 | __email__ = "stephen_purcell at yahoo dot com"
|
|---|
| 49 | __version__ = "#Revision: 1.63 $"[11:-2]
|
|---|
| 50 |
|
|---|
| 51 | import time
|
|---|
| 52 | import sys
|
|---|
| 53 | import traceback
|
|---|
| 54 | import os
|
|---|
| 55 | import types
|
|---|
| 56 |
|
|---|
| 57 | ##############################################################################
|
|---|
| 58 | # Exported classes and functions
|
|---|
| 59 | ##############################################################################
|
|---|
| 60 | __all__ = ['TestResult', 'TestCase', 'TestSuite', 'TextTestRunner',
|
|---|
| 61 | 'TestLoader', 'FunctionTestCase', 'main', 'defaultTestLoader']
|
|---|
| 62 |
|
|---|
| 63 | # Expose obsolete functions for backwards compatibility
|
|---|
| 64 | __all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
|
|---|
| 65 |
|
|---|
| 66 |
|
|---|
| 67 | ##############################################################################
|
|---|
| 68 | # Backward compatibility
|
|---|
| 69 | ##############################################################################
|
|---|
| 70 | if sys.version_info[:2] < (2, 2):
|
|---|
| 71 | False, True = 0, 1
|
|---|
| 72 | def isinstance(obj, clsinfo):
|
|---|
| 73 | import __builtin__
|
|---|
| 74 | if type(clsinfo) in (tuple, list):
|
|---|
| 75 | for cls in clsinfo:
|
|---|
| 76 | if cls is type: cls = types.ClassType
|
|---|
| 77 | if __builtin__.isinstance(obj, cls):
|
|---|
| 78 | return 1
|
|---|
| 79 | return 0
|
|---|
| 80 | else: return __builtin__.isinstance(obj, clsinfo)
|
|---|
| 81 |
|
|---|
| 82 |
|
|---|
| 83 | ##############################################################################
|
|---|
| 84 | # Test framework core
|
|---|
| 85 | ##############################################################################
|
|---|
| 86 |
|
|---|
| 87 | # All classes defined herein are 'new-style' classes, allowing use of 'super()'
|
|---|
| 88 | __metaclass__ = type
|
|---|
| 89 |
|
|---|
| 90 | def _strclass(cls):
|
|---|
| 91 | return "%s.%s" % (cls.__module__, cls.__name__)
|
|---|
| 92 |
|
|---|
| 93 | __unittest = 1
|
|---|
| 94 |
|
|---|
| 95 | class TestResult:
|
|---|
| 96 | """Holder for test result information.
|
|---|
| 97 |
|
|---|
| 98 | Test results are automatically managed by the TestCase and TestSuite
|
|---|
| 99 | classes, and do not need to be explicitly manipulated by writers of tests.
|
|---|
| 100 |
|
|---|
| 101 | Each instance holds the total number of tests run, and collections of
|
|---|
| 102 | failures and errors that occurred among those test runs. The collections
|
|---|
| 103 | contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
|
|---|
| 104 | formatted traceback of the error that occurred.
|
|---|
| 105 | """
|
|---|
| 106 | def __init__(self):
|
|---|
| 107 | self.failures = []
|
|---|
| 108 | self.errors = []
|
|---|
| 109 | self.testsRun = 0
|
|---|
| 110 | self.shouldStop = 0
|
|---|
| 111 |
|
|---|
| 112 | def startTest(self, test):
|
|---|
| 113 | "Called when the given test is about to be run"
|
|---|
| 114 | self.testsRun = self.testsRun + 1
|
|---|
| 115 |
|
|---|
| 116 | def stopTest(self, test):
|
|---|
| 117 | "Called when the given test has been run"
|
|---|
| 118 | pass
|
|---|
| 119 |
|
|---|
| 120 | def addError(self, test, err):
|
|---|
| 121 | """Called when an error has occurred. 'err' is a tuple of values as
|
|---|
| 122 | returned by sys.exc_info().
|
|---|
| 123 | """
|
|---|
| 124 | self.errors.append((test, self._exc_info_to_string(err, test)))
|
|---|
| 125 |
|
|---|
| 126 | def addFailure(self, test, err):
|
|---|
| 127 | """Called when an error has occurred. 'err' is a tuple of values as
|
|---|
| 128 | returned by sys.exc_info()."""
|
|---|
| 129 | self.failures.append((test, self._exc_info_to_string(err, test)))
|
|---|
| 130 |
|
|---|
| 131 | def addSuccess(self, test):
|
|---|
| 132 | "Called when a test has completed successfully"
|
|---|
| 133 | pass
|
|---|
| 134 |
|
|---|
| 135 | def wasSuccessful(self):
|
|---|
| 136 | "Tells whether or not this result was a success"
|
|---|
| 137 | return len(self.failures) == len(self.errors) == 0
|
|---|
| 138 |
|
|---|
| 139 | def stop(self):
|
|---|
| 140 | "Indicates that the tests should be aborted"
|
|---|
| 141 | self.shouldStop = True
|
|---|
| 142 |
|
|---|
| 143 | def _exc_info_to_string(self, err, test):
|
|---|
| 144 | """Converts a sys.exc_info()-style tuple of values into a string."""
|
|---|
| 145 | exctype, value, tb = err
|
|---|
| 146 | # Skip test runner traceback levels
|
|---|
| 147 | while tb and self._is_relevant_tb_level(tb):
|
|---|
| 148 | tb = tb.tb_next
|
|---|
| 149 | if exctype is test.failureException:
|
|---|
| 150 | # Skip assert*() traceback levels
|
|---|
| 151 | length = self._count_relevant_tb_levels(tb)
|
|---|
| 152 | return ''.join(traceback.format_exception(exctype, value, tb, length))
|
|---|
| 153 | return ''.join(traceback.format_exception(exctype, value, tb))
|
|---|
| 154 |
|
|---|
| 155 | def _is_relevant_tb_level(self, tb):
|
|---|
| 156 | return tb.tb_frame.f_globals.has_key('__unittest')
|
|---|
| 157 |
|
|---|
| 158 | def _count_relevant_tb_levels(self, tb):
|
|---|
| 159 | length = 0
|
|---|
| 160 | while tb and not self._is_relevant_tb_level(tb):
|
|---|
| 161 | length += 1
|
|---|
| 162 | tb = tb.tb_next
|
|---|
| 163 | return length
|
|---|
| 164 |
|
|---|
| 165 | def __repr__(self):
|
|---|
| 166 | return "<%s run=%i errors=%i failures=%i>" % \
|
|---|
| 167 | (_strclass(self.__class__), self.testsRun, len(self.errors),
|
|---|
| 168 | len(self.failures))
|
|---|
| 169 |
|
|---|
| 170 | class TestCase:
|
|---|
| 171 | """A class whose instances are single test cases.
|
|---|
| 172 |
|
|---|
| 173 | By default, the test code itself should be placed in a method named
|
|---|
| 174 | 'runTest'.
|
|---|
| 175 |
|
|---|
| 176 | If the fixture may be used for many test cases, create as
|
|---|
| 177 | many test methods as are needed. When instantiating such a TestCase
|
|---|
|
|---|