]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - third_party/Python/module/unittest2/unittest2/suite.py
Vendor import of lldb trunk r256945:
[FreeBSD/FreeBSD.git] / third_party / Python / module / unittest2 / unittest2 / suite.py
1 """TestSuite"""
2
3 import sys
4 import unittest
5 from unittest2 import case, util
6 import six
7
8 __unittest = True
9
10
11 class BaseTestSuite(unittest.TestSuite):
12     """A simple test suite that doesn't provide class or module shared fixtures.
13     """
14     def __init__(self, tests=()):
15         self._tests = []
16         self.addTests(tests)
17
18     def __repr__(self):
19         return "<%s tests=%s>" % (util.strclass(self.__class__), list(self))
20
21     def __eq__(self, other):
22         if not isinstance(other, self.__class__):
23             return NotImplemented
24         return list(self) == list(other)
25
26     def __ne__(self, other):
27         return not self == other
28
29     # Can't guarantee hash invariant, so flag as unhashable
30     __hash__ = None
31
32     def __iter__(self):
33         return iter(self._tests)
34
35     def countTestCases(self):
36         cases = 0
37         for test in self:
38             cases += test.countTestCases()
39         return cases
40
41     def addTest(self, test):
42         # sanity checks
43         if not hasattr(test, '__call__'):
44             raise TypeError("%r is not callable" % (repr(test),))
45         if isinstance(test, type) and issubclass(test,
46                                                  (case.TestCase, TestSuite)):
47             raise TypeError("TestCases and TestSuites must be instantiated "
48                             "before passing them to addTest()")
49         self._tests.append(test)
50
51     def addTests(self, tests):
52         if isinstance(tests, six.string_types):
53             raise TypeError("tests must be an iterable of tests, not a string")
54         for test in tests:
55             self.addTest(test)
56
57     def run(self, result):
58         for test in self:
59             if result.shouldStop:
60                 break
61             test(result)
62         return result
63
64     def __call__(self, *args, **kwds):
65         return self.run(*args, **kwds)
66
67     def debug(self):
68         """Run the tests without collecting errors in a TestResult"""
69         for test in self:
70             test.debug()
71
72
73 class TestSuite(BaseTestSuite):
74     """A test suite is a composite test consisting of a number of TestCases.
75
76     For use, create an instance of TestSuite, then add test case instances.
77     When all tests have been added, the suite can be passed to a test
78     runner, such as TextTestRunner. It will run the individual test cases
79     in the order in which they were added, aggregating the results. When
80     subclassing, do not forget to call the base class constructor.
81     """
82     
83
84     def run(self, result):
85         self._wrapped_run(result)
86         self._tearDownPreviousClass(None, result)
87         self._handleModuleTearDown(result)
88         return result
89
90     def debug(self):
91         """Run the tests without collecting errors in a TestResult"""
92         debug = _DebugResult()
93         self._wrapped_run(debug, True)
94         self._tearDownPreviousClass(None, debug)
95         self._handleModuleTearDown(debug)
96
97     ################################
98     # private methods
99     def _wrapped_run(self, result, debug=False):
100         for test in self:
101             if result.shouldStop:
102                 break
103             
104             if _isnotsuite(test):
105                 self._tearDownPreviousClass(test, result)
106                 self._handleModuleFixture(test, result)
107                 self._handleClassSetUp(test, result)
108                 result._previousTestClass = test.__class__
109                 
110                 if (getattr(test.__class__, '_classSetupFailed', False) or 
111                     getattr(result, '_moduleSetUpFailed', False)):
112                     continue
113             
114             if hasattr(test, '_wrapped_run'):
115                 test._wrapped_run(result, debug)
116             elif not debug:
117                 test(result)
118             else:
119                 test.debug()
120     
121     def _handleClassSetUp(self, test, result):
122         previousClass = getattr(result, '_previousTestClass', None)
123         currentClass = test.__class__
124         if currentClass == previousClass:
125             return
126         if result._moduleSetUpFailed:
127             return
128         if getattr(currentClass, "__unittest_skip__", False):
129             return
130         
131         try:
132             currentClass._classSetupFailed = False
133         except TypeError:
134             # test may actually be a function
135             # so its class will be a builtin-type
136             pass
137             
138         setUpClass = getattr(currentClass, 'setUpClass', None)
139         if setUpClass is not None:
140             try:
141                 setUpClass()
142             except Exception as e:
143                 if isinstance(result, _DebugResult):
144                     raise
145                 currentClass._classSetupFailed = True
146                 className = util.strclass(currentClass)
147                 errorName = 'setUpClass (%s)' % className
148                 self._addClassOrModuleLevelException(result, e, errorName)
149     
150     def _get_previous_module(self, result):
151         previousModule = None
152         previousClass = getattr(result, '_previousTestClass', None)
153         if previousClass is not None:
154             previousModule = previousClass.__module__
155         return previousModule
156         
157         
158     def _handleModuleFixture(self, test, result):
159         previousModule = self._get_previous_module(result)
160         currentModule = test.__class__.__module__
161         if currentModule == previousModule:
162             return
163         
164         self._handleModuleTearDown(result)
165
166         
167         result._moduleSetUpFailed = False
168         try:
169             module = sys.modules[currentModule]
170         except KeyError:
171             return
172         setUpModule = getattr(module, 'setUpModule', None)
173         if setUpModule is not None:
174             try:
175                 setUpModule()
176             except Exception as e:
177                 if isinstance(result, _DebugResult):
178                     raise
179                 result._moduleSetUpFailed = True
180                 errorName = 'setUpModule (%s)' % currentModule
181                 self._addClassOrModuleLevelException(result, e, errorName)
182
183     def _addClassOrModuleLevelException(self, result, exception, errorName):
184         error = _ErrorHolder(errorName)
185         addSkip = getattr(result, 'addSkip', None)
186         if addSkip is not None and isinstance(exception, case.SkipTest):
187             addSkip(error, str(exception))
188         else:
189             result.addError(error, sys.exc_info())
190     
191     def _handleModuleTearDown(self, result):
192         previousModule = self._get_previous_module(result)
193         if previousModule is None:
194             return
195         if result._moduleSetUpFailed:
196             return
197             
198         try:
199             module = sys.modules[previousModule]
200         except KeyError:
201             return
202
203         tearDownModule = getattr(module, 'tearDownModule', None)
204         if tearDownModule is not None:
205             try:
206                 tearDownModule()
207             except Exception as e:
208                 if isinstance(result, _DebugResult):
209                     raise
210                 errorName = 'tearDownModule (%s)' % previousModule
211                 self._addClassOrModuleLevelException(result, e, errorName)
212     
213     def _tearDownPreviousClass(self, test, result):
214         previousClass = getattr(result, '_previousTestClass', None)
215         currentClass = test.__class__
216         if currentClass == previousClass:
217             return
218         if getattr(previousClass, '_classSetupFailed', False):
219             return
220         if getattr(result, '_moduleSetUpFailed', False):
221             return
222         if getattr(previousClass, "__unittest_skip__", False):
223             return
224         
225         tearDownClass = getattr(previousClass, 'tearDownClass', None)
226         if tearDownClass is not None:
227             try:
228                 tearDownClass()
229             except Exception as e:
230                 if isinstance(result, _DebugResult):
231                     raise
232                 className = util.strclass(previousClass)
233                 errorName = 'tearDownClass (%s)' % className
234                 self._addClassOrModuleLevelException(result, e, errorName)
235
236
237 class _ErrorHolder(object):
238     """
239     Placeholder for a TestCase inside a result. As far as a TestResult
240     is concerned, this looks exactly like a unit test. Used to insert
241     arbitrary errors into a test suite run.
242     """
243     # Inspired by the ErrorHolder from Twisted:
244     # http://twistedmatrix.com/trac/browser/trunk/twisted/trial/runner.py
245
246     # attribute used by TestResult._exc_info_to_string
247     failureException = None
248
249     def __init__(self, description):
250         self.description = description
251
252     def id(self):
253         return self.description
254
255     def shortDescription(self):
256         return None
257
258     def __repr__(self):
259         return "<ErrorHolder description=%r>" % (self.description,)
260
261     def __str__(self):
262         return self.id()
263
264     def run(self, result):
265         # could call result.addError(...) - but this test-like object
266         # shouldn't be run anyway
267         pass
268
269     def __call__(self, result):
270         return self.run(result)
271
272     def countTestCases(self):
273         return 0
274
275 def _isnotsuite(test):
276     "A crude way to tell apart testcases and suites with duck-typing"
277     try:
278         iter(test)
279     except TypeError:
280         return True
281     return False
282
283
284 class _DebugResult(object):
285     "Used by the TestSuite to hold previous class when running in debug."
286     _previousTestClass = None
287     _moduleSetUpFailed = False
288     shouldStop = False