1
# Copyright (C) 2005-2010 Canonical Ltd
1
# Copyright (C) 2004, 2005, 2006 Canonical Ltd
2
2
# Author: Robert Collins <robert.collins@canonical.com>
4
4
# This program is free software; you can redistribute it and/or modify
14
14
# You should have received a copy of the GNU General Public License
15
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
47
47
def visitTests(suite, visitor):
48
48
"""A foreign method for visiting the tests in a test suite."""
49
49
for test in suite._tests:
50
#Abusing types to avoid monkey patching unittest.TestCase.
50
#Abusing types to avoid monkey patching unittest.TestCase.
51
51
# Maybe that would be better?
53
53
test.visit(visitor)
59
59
visitTests(test, visitor)
61
61
print "unvisitable non-unittest.TestCase element %r (%r)" % (test, test.__class__)
64
64
class TestSuite(unittest.TestSuite):
65
65
"""I am an extended TestSuite with a visitor interface.
72
72
visitor.visitSuite(self)
73
73
visitTests(self, visitor)
75
def run(self, result):
76
"""Run the tests in the suite, discarding references after running."""
82
self._tests = reversed(tests)
84
tests.pop().run(result)
88
76
class TestLoader(unittest.TestLoader):
89
77
"""Custom TestLoader to extend the stock python one."""
91
79
suiteClass = TestSuite
92
# Memoize test names by test class dict
95
81
def loadTestsFromModuleNames(self, names):
96
82
"""use a custom means to load tests from modules.
98
There is an undesirable glitch in the python TestLoader where a
99
import error is ignore. We think this can be solved by ensuring the
84
There is an undesirable glitch in the python TestLoader where a
85
import error is ignore. We think this can be solved by ensuring the
100
86
requested name is resolvable, if its not raising the original error.
102
88
result = self.suiteClass()
103
89
for name in names:
104
result.addTests(self.loadTestsFromModuleName(name))
107
def loadTestsFromModuleName(self, name):
108
result = self.suiteClass()
109
module = _load_module_by_name(name)
111
result.addTests(self.loadTestsFromModule(module))
90
module = _load_module_by_name(name)
91
result.addTests(self.loadTestsFromModule(module))
114
94
def loadTestsFromModule(self, module):
119
99
regular python loadTestsFromModule.
121
101
If a load_tests attribute is found, it is called and the result is
124
104
load_tests should be defined like so:
125
105
>>> def load_tests(standard_tests, module, loader):
143
123
return basic_tests
145
def getTestCaseNames(self, test_case_class):
146
test_fn_names = self.test_func_names.get(test_case_class, None)
147
if test_fn_names is not None:
148
# We already know them
151
test_fn_names = unittest.TestLoader.getTestCaseNames(self,
153
self.test_func_names[test_case_class] = test_fn_names
157
class FilteredByModuleTestLoader(TestLoader):
158
"""A test loader that import only the needed modules."""
160
def __init__(self, needs_module):
163
:param needs_module: a callable taking a module name as a
164
parameter returing True if the module should be loaded.
166
TestLoader.__init__(self)
167
self.needs_module = needs_module
169
def loadTestsFromModuleName(self, name):
170
if self.needs_module(name):
171
return TestLoader.loadTestsFromModuleName(self, name)
173
return self.suiteClass()
176
126
def _load_module_by_name(mod_name):
177
127
parts = mod_name.split('.')