ยปCore Development>Code coverage>Lib/unittest/suite.py

Python code coverage for Lib/unittest/suite.py

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