blob: e860debc0f39204a4e58ea71ef244144d91b8d7b [file] [log] [blame]
Benjamin Petersonbed7d042009-07-19 21:01:52 +00001"""Loading unittests."""
2
3import os
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +00004import re
Benjamin Petersonbed7d042009-07-19 21:01:52 +00005import sys
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +00006import traceback
Benjamin Petersonbed7d042009-07-19 21:01:52 +00007import types
Raymond Hettingerc50846a2010-04-05 18:56:31 +00008import functools
Barry Warsawd78742a2014-09-08 14:21:37 -04009import warnings
Benjamin Petersonbed7d042009-07-19 21:01:52 +000010
11from fnmatch import fnmatch
12
13from . import case, suite, util
14
Benjamin Petersondccc1fc2010-03-22 00:15:53 +000015__unittest = True
Benjamin Petersonbed7d042009-07-19 21:01:52 +000016
Brett Cannonf299abd2015-04-13 14:21:02 -040017# what about .pyc (etc)
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +000018# we would need to avoid loading the same tests multiple times
Brett Cannonf299abd2015-04-13 14:21:02 -040019# from '.py', *and* '.pyc'
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +000020VALID_MODULE_NAME = re.compile(r'[_a-z]\w*\.py$', re.IGNORECASE)
21
22
Antoine Pitroud8337792015-03-18 23:56:46 +010023class _FailedTest(case.TestCase):
24 _testMethodName = None
25
26 def __init__(self, method_name, exception):
27 self._exception = exception
28 super(_FailedTest, self).__init__(method_name)
29
30 def __getattr__(self, name):
31 if name != self._testMethodName:
32 return super(_FailedTest, self).__getattr__(name)
33 def testFailure():
34 raise self._exception
35 return testFailure
36
37
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +000038def _make_failed_import_test(name, suiteClass):
Robert Collinsf920c212014-10-20 13:24:05 +130039 message = 'Failed to import test module: %s\n%s' % (
40 name, traceback.format_exc())
Antoine Pitrou8eef6a92015-03-19 00:01:37 +010041 return _make_failed_test(name, ImportError(message), suiteClass, message)
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +000042
Benjamin Peterson886af962010-03-21 23:13:07 +000043def _make_failed_load_tests(name, exception, suiteClass):
Robert Collinsf920c212014-10-20 13:24:05 +130044 message = 'Failed to call load_tests:\n%s' % (traceback.format_exc(),)
45 return _make_failed_test(
Antoine Pitrou8eef6a92015-03-19 00:01:37 +010046 name, exception, suiteClass, message)
Benjamin Peterson886af962010-03-21 23:13:07 +000047
Antoine Pitrou8eef6a92015-03-19 00:01:37 +010048def _make_failed_test(methodname, exception, suiteClass, message):
Antoine Pitroud8337792015-03-18 23:56:46 +010049 test = _FailedTest(methodname, exception)
Antoine Pitrou8eef6a92015-03-19 00:01:37 +010050 return suiteClass((test,)), message
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +000051
Ezio Melottieae2b382013-03-01 14:47:50 +020052def _make_skipped_test(methodname, exception, suiteClass):
53 @case.skip(str(exception))
54 def testSkipped(self):
55 pass
56 attrs = {methodname: testSkipped}
57 TestClass = type("ModuleSkipped", (case.TestCase,), attrs)
58 return suiteClass((TestClass(methodname),))
59
Michael Foorde01c62c2012-03-13 00:09:54 -070060def _jython_aware_splitext(path):
61 if path.lower().endswith('$py.class'):
62 return path[:-9]
63 return os.path.splitext(path)[0]
64
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +000065
Benjamin Petersonbed7d042009-07-19 21:01:52 +000066class TestLoader(object):
67 """
68 This class is responsible for loading tests according to various criteria
69 and returning them wrapped in a TestSuite
70 """
71 testMethodPrefix = 'test'
72 sortTestMethodsUsing = staticmethod(util.three_way_cmp)
73 suiteClass = suite.TestSuite
74 _top_level_dir = None
75
Robert Collinsf920c212014-10-20 13:24:05 +130076 def __init__(self):
77 super(TestLoader, self).__init__()
78 self.errors = []
Robert Collinsbf2bda32014-11-05 03:09:01 +130079 # Tracks packages which we have called into via load_tests, to
80 # avoid infinite re-entrancy.
81 self._loading_packages = set()
Robert Collinsf920c212014-10-20 13:24:05 +130082
Benjamin Petersonbed7d042009-07-19 21:01:52 +000083 def loadTestsFromTestCase(self, testCaseClass):
Martin Panter37f183d2017-01-18 12:06:38 +000084 """Return a suite of all test cases contained in testCaseClass"""
Benjamin Petersonbed7d042009-07-19 21:01:52 +000085 if issubclass(testCaseClass, suite.TestSuite):
Michael Foorde28bb152013-11-23 13:29:23 +000086 raise TypeError("Test cases should not be derived from "
87 "TestSuite. Maybe you meant to derive from "
88 "TestCase?")
Benjamin Petersonbed7d042009-07-19 21:01:52 +000089 testCaseNames = self.getTestCaseNames(testCaseClass)
90 if not testCaseNames and hasattr(testCaseClass, 'runTest'):
91 testCaseNames = ['runTest']
92 loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames))
93 return loaded_suite
94
Barry Warsawd78742a2014-09-08 14:21:37 -040095 # XXX After Python 3.5, remove backward compatibility hacks for
96 # use_load_tests deprecation via *args and **kws. See issue 16662.
97 def loadTestsFromModule(self, module, *args, pattern=None, **kws):
Martin Panter37f183d2017-01-18 12:06:38 +000098 """Return a suite of all test cases contained in the given module"""
Barry Warsawd78742a2014-09-08 14:21:37 -040099 # This method used to take an undocumented and unofficial
100 # use_load_tests argument. For backward compatibility, we still
101 # accept the argument (which can also be the first position) but we
102 # ignore it and issue a deprecation warning if it's present.
Barry Warsawbb1e3f12014-09-08 17:29:02 -0400103 if len(args) > 0 or 'use_load_tests' in kws:
Barry Warsawd78742a2014-09-08 14:21:37 -0400104 warnings.warn('use_load_tests is deprecated and ignored',
105 DeprecationWarning)
106 kws.pop('use_load_tests', None)
107 if len(args) > 1:
Barry Warsawbb1e3f12014-09-08 17:29:02 -0400108 # Complain about the number of arguments, but don't forget the
109 # required `module` argument.
110 complaint = len(args) + 1
111 raise TypeError('loadTestsFromModule() takes 1 positional argument but {} were given'.format(complaint))
Barry Warsawd78742a2014-09-08 14:21:37 -0400112 if len(kws) != 0:
113 # Since the keyword arguments are unsorted (see PEP 468), just
114 # pick the alphabetically sorted first argument to complain about,
115 # if multiple were given. At least the error message will be
116 # predictable.
117 complaint = sorted(kws)[0]
118 raise TypeError("loadTestsFromModule() got an unexpected keyword argument '{}'".format(complaint))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000119 tests = []
120 for name in dir(module):
121 obj = getattr(module, name)
122 if isinstance(obj, type) and issubclass(obj, case.TestCase):
123 tests.append(self.loadTestsFromTestCase(obj))
124
125 load_tests = getattr(module, 'load_tests', None)
Michael Foord41647d62010-02-06 00:26:13 +0000126 tests = self.suiteClass(tests)
Barry Warsawd78742a2014-09-08 14:21:37 -0400127 if load_tests is not None:
Benjamin Peterson886af962010-03-21 23:13:07 +0000128 try:
Barry Warsawd78742a2014-09-08 14:21:37 -0400129 return load_tests(self, tests, pattern)
Benjamin Peterson886af962010-03-21 23:13:07 +0000130 except Exception as e:
Robert Collinsf920c212014-10-20 13:24:05 +1300131 error_case, error_message = _make_failed_load_tests(
132 module.__name__, e, self.suiteClass)
133 self.errors.append(error_message)
134 return error_case
Michael Foord41647d62010-02-06 00:26:13 +0000135 return tests
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000136
137 def loadTestsFromName(self, name, module=None):
Martin Panter37f183d2017-01-18 12:06:38 +0000138 """Return a suite of all test cases given a string specifier.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000139
140 The name may resolve either to a module, a test case class, a
141 test method within a test case class, or a callable object which
142 returns a TestCase or TestSuite instance.
143
144 The method optionally resolves the names relative to a given module.
145 """
146 parts = name.split('.')
Robert Collins659dd622014-10-30 08:27:27 +1300147 error_case, error_message = None, None
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000148 if module is None:
149 parts_copy = parts[:]
150 while parts_copy:
151 try:
Robert Collins659dd622014-10-30 08:27:27 +1300152 module_name = '.'.join(parts_copy)
153 module = __import__(module_name)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000154 break
155 except ImportError:
Robert Collins659dd622014-10-30 08:27:27 +1300156 next_attribute = parts_copy.pop()
157 # Last error so we can give it to the user if needed.
158 error_case, error_message = _make_failed_import_test(
159 next_attribute, self.suiteClass)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000160 if not parts_copy:
Robert Collins659dd622014-10-30 08:27:27 +1300161 # Even the top level import failed: report that error.
162 self.errors.append(error_message)
163 return error_case
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000164 parts = parts[1:]
165 obj = module
166 for part in parts:
Robert Collins659dd622014-10-30 08:27:27 +1300167 try:
168 parent, obj = obj, getattr(obj, part)
169 except AttributeError as e:
170 # We can't traverse some part of the name.
171 if (getattr(obj, '__path__', None) is not None
172 and error_case is not None):
173 # This is a package (no __path__ per importlib docs), and we
174 # encountered an error importing something. We cannot tell
175 # the difference between package.WrongNameTestClass and
176 # package.wrong_module_name so we just report the
177 # ImportError - it is more informative.
178 self.errors.append(error_message)
179 return error_case
180 else:
181 # Otherwise, we signal that an AttributeError has occurred.
182 error_case, error_message = _make_failed_test(
Antoine Pitrou8eef6a92015-03-19 00:01:37 +0100183 part, e, self.suiteClass,
Robert Collins659dd622014-10-30 08:27:27 +1300184 'Failed to access attribute:\n%s' % (
185 traceback.format_exc(),))
186 self.errors.append(error_message)
187 return error_case
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000188
189 if isinstance(obj, types.ModuleType):
190 return self.loadTestsFromModule(obj)
191 elif isinstance(obj, type) and issubclass(obj, case.TestCase):
192 return self.loadTestsFromTestCase(obj)
193 elif (isinstance(obj, types.FunctionType) and
194 isinstance(parent, type) and
195 issubclass(parent, case.TestCase)):
R David Murray5e2f5932013-04-11 08:55:45 -0400196 name = parts[-1]
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000197 inst = parent(name)
198 # static methods follow a different path
199 if not isinstance(getattr(inst, name), types.FunctionType):
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000200 return self.suiteClass([inst])
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000201 elif isinstance(obj, suite.TestSuite):
202 return obj
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200203 if callable(obj):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000204 test = obj()
205 if isinstance(test, suite.TestSuite):
206 return test
207 elif isinstance(test, case.TestCase):
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000208 return self.suiteClass([test])
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000209 else:
210 raise TypeError("calling %s returned %s, not a test" %
211 (obj, test))
212 else:
213 raise TypeError("don't know how to make test from: %s" % obj)
214
215 def loadTestsFromNames(self, names, module=None):
Martin Panter37f183d2017-01-18 12:06:38 +0000216 """Return a suite of all test cases found using the given sequence
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000217 of string specifiers. See 'loadTestsFromName()'.
218 """
219 suites = [self.loadTestsFromName(name, module) for name in names]
220 return self.suiteClass(suites)
221
222 def getTestCaseNames(self, testCaseClass):
223 """Return a sorted sequence of method names found within testCaseClass
224 """
225 def isTestMethod(attrname, testCaseClass=testCaseClass,
226 prefix=self.testMethodPrefix):
227 return attrname.startswith(prefix) and \
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200228 callable(getattr(testCaseClass, attrname))
Senthil Kumaranf27be5c2011-11-25 02:08:39 +0800229 testFnNames = list(filter(isTestMethod, dir(testCaseClass)))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000230 if self.sortTestMethodsUsing:
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000231 testFnNames.sort(key=functools.cmp_to_key(self.sortTestMethodsUsing))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000232 return testFnNames
233
234 def discover(self, start_dir, pattern='test*.py', top_level_dir=None):
235 """Find and return all test modules from the specified start
Michael Foord6bcfade2010-11-20 17:22:21 +0000236 directory, recursing into subdirectories to find them and return all
237 tests found within them. Only test files that match the pattern will
238 be loaded. (Using shell style pattern matching.)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000239
240 All test modules must be importable from the top level of the project.
241 If the start directory is not the top level directory then the top
242 level directory must be specified separately.
243
244 If a test package name (directory with '__init__.py') matches the
245 pattern then the package will be checked for a 'load_tests' function. If
Robert Collinsbf2bda32014-11-05 03:09:01 +1300246 this exists then it will be called with (loader, tests, pattern) unless
247 the package has already had load_tests called from the same discovery
248 invocation, in which case the package module object is not scanned for
249 tests - this ensures that when a package uses discover to further
250 discover child tests that infinite recursion does not happen.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000251
Robert Collinsbf2bda32014-11-05 03:09:01 +1300252 If load_tests exists then discovery does *not* recurse into the package,
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000253 load_tests is responsible for loading all tests in the package.
254
255 The pattern is deliberately not stored as a loader attribute so that
256 packages can continue discovery themselves. top_level_dir is stored so
257 load_tests does not need to pass this argument in to loader.discover().
Michael Foord80cbc9e2013-03-18 17:50:12 -0700258
259 Paths are sorted before being imported to ensure reproducible execution
260 order even on filesystems with non-alphabetical ordering like ext3/4.
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000261 """
Benjamin Petersonb48af542010-04-11 20:43:16 +0000262 set_implicit_top = False
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000263 if top_level_dir is None and self._top_level_dir is not None:
264 # make top_level_dir optional if called from load_tests in a package
265 top_level_dir = self._top_level_dir
266 elif top_level_dir is None:
Benjamin Petersonb48af542010-04-11 20:43:16 +0000267 set_implicit_top = True
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000268 top_level_dir = start_dir
269
Benjamin Petersonb48af542010-04-11 20:43:16 +0000270 top_level_dir = os.path.abspath(top_level_dir)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000271
272 if not top_level_dir in sys.path:
273 # all test modules must be importable from the top level directory
Michael Foord3b2494f2010-05-07 23:42:40 +0000274 # should we *unconditionally* put the start directory in first
275 # in sys.path to minimise likelihood of conflicts between installed
276 # modules and development versions?
277 sys.path.insert(0, top_level_dir)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000278 self._top_level_dir = top_level_dir
279
Benjamin Petersonb48af542010-04-11 20:43:16 +0000280 is_not_importable = False
Michael Foorde28bb152013-11-23 13:29:23 +0000281 is_namespace = False
282 tests = []
Benjamin Petersonb48af542010-04-11 20:43:16 +0000283 if os.path.isdir(os.path.abspath(start_dir)):
284 start_dir = os.path.abspath(start_dir)
285 if start_dir != top_level_dir:
286 is_not_importable = not os.path.isfile(os.path.join(start_dir, '__init__.py'))
287 else:
288 # support for discovery from dotted module names
289 try:
290 __import__(start_dir)
291 except ImportError:
292 is_not_importable = True
293 else:
294 the_module = sys.modules[start_dir]
295 top_part = start_dir.split('.')[0]
Michael Foorde28bb152013-11-23 13:29:23 +0000296 try:
297 start_dir = os.path.abspath(
298 os.path.dirname((the_module.__file__)))
299 except AttributeError:
300 # look for namespace packages
301 try:
302 spec = the_module.__spec__
303 except AttributeError:
304 spec = None
305
306 if spec and spec.loader is None:
307 if spec.submodule_search_locations is not None:
308 is_namespace = True
309
310 for path in the_module.__path__:
311 if (not set_implicit_top and
312 not path.startswith(top_level_dir)):
313 continue
314 self._top_level_dir = \
315 (path.split(the_module.__name__
316 .replace(".", os.path.sep))[0])
317 tests.extend(self._find_tests(path,
318 pattern,
319 namespace=True))
320 elif the_module.__name__ in sys.builtin_module_names:
321 # builtin module
322 raise TypeError('Can not use builtin modules '
323 'as dotted module names') from None
324 else:
325 raise TypeError(
326 'don\'t know how to discover from {!r}'
327 .format(the_module)) from None
328
Benjamin Petersonb48af542010-04-11 20:43:16 +0000329 if set_implicit_top:
Michael Foorde28bb152013-11-23 13:29:23 +0000330 if not is_namespace:
331 self._top_level_dir = \
332 self._get_directory_containing_module(top_part)
333 sys.path.remove(top_level_dir)
334 else:
335 sys.path.remove(top_level_dir)
Benjamin Petersonb48af542010-04-11 20:43:16 +0000336
337 if is_not_importable:
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000338 raise ImportError('Start directory is not importable: %r' % start_dir)
339
Michael Foorde28bb152013-11-23 13:29:23 +0000340 if not is_namespace:
341 tests = list(self._find_tests(start_dir, pattern))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000342 return self.suiteClass(tests)
343
Benjamin Petersonb48af542010-04-11 20:43:16 +0000344 def _get_directory_containing_module(self, module_name):
345 module = sys.modules[module_name]
346 full_path = os.path.abspath(module.__file__)
347
348 if os.path.basename(full_path).lower().startswith('__init__.py'):
349 return os.path.dirname(os.path.dirname(full_path))
350 else:
351 # here we have been given a module rather than a package - so
352 # all we can do is search the *same* directory the module is in
353 # should an exception be raised instead
354 return os.path.dirname(full_path)
355
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000356 def _get_name_from_path(self, path):
Robert Collins68b11d12014-11-05 03:43:36 +1300357 if path == self._top_level_dir:
358 return '.'
Michael Foorde01c62c2012-03-13 00:09:54 -0700359 path = _jython_aware_splitext(os.path.normpath(path))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000360
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000361 _relpath = os.path.relpath(path, self._top_level_dir)
362 assert not os.path.isabs(_relpath), "Path must be within the project"
363 assert not _relpath.startswith('..'), "Path must be within the project"
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000364
Benjamin Peterson4ac9ce42009-10-04 14:49:41 +0000365 name = _relpath.replace(os.path.sep, '.')
366 return name
367
368 def _get_module_from_name(self, name):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000369 __import__(name)
370 return sys.modules[name]
371
Michael Foord4107d312010-06-05 10:45:41 +0000372 def _match_path(self, path, full_path, pattern):
373 # override this method to use alternative matching strategy
374 return fnmatch(path, pattern)
375
Michael Foorde28bb152013-11-23 13:29:23 +0000376 def _find_tests(self, start_dir, pattern, namespace=False):
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000377 """Used by discovery. Yields test suites it loads."""
Robert Collinsbf2bda32014-11-05 03:09:01 +1300378 # Handle the __init__ in this package
379 name = self._get_name_from_path(start_dir)
380 # name is '.' when start_dir == top_level_dir (and top_level_dir is by
381 # definition not a package).
382 if name != '.' and name not in self._loading_packages:
383 # name is in self._loading_packages while we have called into
384 # loadTestsFromModule with name.
385 tests, should_recurse = self._find_test_path(
386 start_dir, pattern, namespace)
387 if tests is not None:
388 yield tests
389 if not should_recurse:
Martin Panter46f50722016-05-26 05:35:26 +0000390 # Either an error occurred, or load_tests was used by the
Robert Collinsbf2bda32014-11-05 03:09:01 +1300391 # package.
392 return
393 # Handle the contents.
Michael Foord80cbc9e2013-03-18 17:50:12 -0700394 paths = sorted(os.listdir(start_dir))
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000395 for path in paths:
396 full_path = os.path.join(start_dir, path)
Robert Collinsbf2bda32014-11-05 03:09:01 +1300397 tests, should_recurse = self._find_test_path(
398 full_path, pattern, namespace)
399 if tests is not None:
400 yield tests
401 if should_recurse:
402 # we found a package that didn't use load_tests.
Michael Foord4107d312010-06-05 10:45:41 +0000403 name = self._get_name_from_path(full_path)
Robert Collinsbf2bda32014-11-05 03:09:01 +1300404 self._loading_packages.add(name)
Michael Foord4107d312010-06-05 10:45:41 +0000405 try:
Robert Collinsbf2bda32014-11-05 03:09:01 +1300406 yield from self._find_tests(full_path, pattern, namespace)
407 finally:
408 self._loading_packages.discard(name)
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000409
Robert Collinsbf2bda32014-11-05 03:09:01 +1300410 def _find_test_path(self, full_path, pattern, namespace=False):
411 """Used by discovery.
412
413 Loads tests from a single file, or a directories' __init__.py when
414 passed the directory.
415
416 Returns a tuple (None_or_tests_from_file, should_recurse).
417 """
418 basename = os.path.basename(full_path)
419 if os.path.isfile(full_path):
420 if not VALID_MODULE_NAME.match(basename):
421 # valid Python identifiers only
422 return None, False
423 if not self._match_path(basename, full_path, pattern):
424 return None, False
425 # if the test file matches, load it
426 name = self._get_name_from_path(full_path)
427 try:
428 module = self._get_module_from_name(name)
429 except case.SkipTest as e:
430 return _make_skipped_test(name, e, self.suiteClass), False
431 except:
432 error_case, error_message = \
433 _make_failed_import_test(name, self.suiteClass)
434 self.errors.append(error_message)
435 return error_case, False
436 else:
437 mod_file = os.path.abspath(
438 getattr(module, '__file__', full_path))
439 realpath = _jython_aware_splitext(
440 os.path.realpath(mod_file))
441 fullpath_noext = _jython_aware_splitext(
442 os.path.realpath(full_path))
443 if realpath.lower() != fullpath_noext.lower():
444 module_dir = os.path.dirname(realpath)
445 mod_name = _jython_aware_splitext(
446 os.path.basename(full_path))
447 expected_dir = os.path.dirname(full_path)
448 msg = ("%r module incorrectly imported from %r. Expected "
449 "%r. Is this module globally installed?")
450 raise ImportError(
451 msg % (mod_name, module_dir, expected_dir))
452 return self.loadTestsFromModule(module, pattern=pattern), False
453 elif os.path.isdir(full_path):
454 if (not namespace and
455 not os.path.isfile(os.path.join(full_path, '__init__.py'))):
456 return None, False
457
458 load_tests = None
459 tests = None
460 name = self._get_name_from_path(full_path)
461 try:
462 package = self._get_module_from_name(name)
463 except case.SkipTest as e:
464 return _make_skipped_test(name, e, self.suiteClass), False
465 except:
466 error_case, error_message = \
467 _make_failed_import_test(name, self.suiteClass)
468 self.errors.append(error_message)
469 return error_case, False
470 else:
471 load_tests = getattr(package, 'load_tests', None)
472 # Mark this package as being in load_tests (possibly ;))
473 self._loading_packages.add(name)
Barry Warsawd78742a2014-09-08 14:21:37 -0400474 try:
Barry Warsawd78742a2014-09-08 14:21:37 -0400475 tests = self.loadTestsFromModule(package, pattern=pattern)
Barry Warsawd78742a2014-09-08 14:21:37 -0400476 if load_tests is not None:
Robert Collinsbf2bda32014-11-05 03:09:01 +1300477 # loadTestsFromModule(package) has loaded tests for us.
478 return tests, False
479 return tests, True
480 finally:
481 self._loading_packages.discard(name)
Robert Collinsecd53832016-03-15 13:29:17 +1300482 else:
483 return None, False
Barry Warsawd78742a2014-09-08 14:21:37 -0400484
Benjamin Petersonbed7d042009-07-19 21:01:52 +0000485
486defaultTestLoader = TestLoader()
487
488
489def _makeLoader(prefix, sortUsing, suiteClass=None):
490 loader = TestLoader()
491 loader.sortTestMethodsUsing = sortUsing
492 loader.testMethodPrefix = prefix
493 if suiteClass:
494 loader.suiteClass = suiteClass
495 return loader
496
497def getTestCaseNames(testCaseClass, prefix, sortUsing=util.three_way_cmp):
498 return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
499
500def makeSuite(testCaseClass, prefix='test', sortUsing=util.three_way_cmp,
501 suiteClass=suite.TestSuite):
502 return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(
503 testCaseClass)
504
505def findTestCases(module, prefix='test', sortUsing=util.three_way_cmp,
506 suiteClass=suite.TestSuite):
507 return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(\
508 module)