diff options
Diffstat (limited to 'Lib/unittest/loader.py')
-rw-r--r-- | Lib/unittest/loader.py | 57 |
1 files changed, 34 insertions, 23 deletions
diff --git a/Lib/unittest/loader.py b/Lib/unittest/loader.py index e88f536b394..541884e4161 100644 --- a/Lib/unittest/loader.py +++ b/Lib/unittest/loader.py @@ -5,11 +5,11 @@ import re import sys import traceback import types +import functools -from functools import cmp_to_key as _CmpToKey from fnmatch import fnmatch -from . import case, suite +from . import case, suite, util __unittest = True @@ -34,6 +34,11 @@ def _make_failed_test(classname, methodname, exception, suiteClass): TestClass = type(classname, (case.TestCase,), attrs) return suiteClass((TestClass(methodname),)) +def _jython_aware_splitext(path): + if path.lower().endswith('$py.class'): + return path[:-9] + return os.path.splitext(path)[0] + class TestLoader(object): """ @@ -41,7 +46,7 @@ class TestLoader(object): and returning them wrapped in a TestSuite """ testMethodPrefix = 'test' - sortTestMethodsUsing = cmp + sortTestMethodsUsing = staticmethod(util.three_way_cmp) suiteClass = suite.TestSuite _top_level_dir = None @@ -69,7 +74,7 @@ class TestLoader(object): if use_load_tests and load_tests is not None: try: return load_tests(self, tests, None) - except Exception, e: + except Exception as e: return _make_failed_load_tests(module.__name__, e, self.suiteClass) return tests @@ -103,13 +108,17 @@ class TestLoader(object): return self.loadTestsFromModule(obj) elif isinstance(obj, type) and issubclass(obj, case.TestCase): return self.loadTestsFromTestCase(obj) - elif (isinstance(obj, types.UnboundMethodType) and + elif (isinstance(obj, types.FunctionType) and isinstance(parent, type) and issubclass(parent, case.TestCase)): - return self.suiteClass([parent(obj.__name__)]) + name = obj.__name__ + inst = parent(name) + # static methods follow a different path + if not isinstance(getattr(inst, name), types.FunctionType): + return self.suiteClass([inst]) elif isinstance(obj, suite.TestSuite): return obj - elif hasattr(obj, '__call__'): + if callable(obj): test = obj() if isinstance(test, suite.TestSuite): return test @@ -134,17 +143,17 @@ class TestLoader(object): def isTestMethod(attrname, testCaseClass=testCaseClass, prefix=self.testMethodPrefix): return attrname.startswith(prefix) and \ - hasattr(getattr(testCaseClass, attrname), '__call__') - testFnNames = filter(isTestMethod, dir(testCaseClass)) + callable(getattr(testCaseClass, attrname)) + testFnNames = list(filter(isTestMethod, dir(testCaseClass))) if self.sortTestMethodsUsing: - testFnNames.sort(key=_CmpToKey(self.sortTestMethodsUsing)) + testFnNames.sort(key=functools.cmp_to_key(self.sortTestMethodsUsing)) return testFnNames def discover(self, start_dir, pattern='test*.py', top_level_dir=None): """Find and return all test modules from the specified start - directory, recursing into subdirectories to find them. Only test files - that match the pattern will be loaded. (Using shell style pattern - matching.) + directory, recursing into subdirectories to find them and return all + tests found within them. Only test files that match the pattern will + be loaded. (Using shell style pattern matching.) All test modules must be importable from the top level of the project. If the start directory is not the top level directory then the top @@ -217,7 +226,7 @@ class TestLoader(object): return os.path.dirname(full_path) def _get_name_from_path(self, path): - path = os.path.splitext(os.path.normpath(path))[0] + path = _jython_aware_splitext(os.path.normpath(path)) _relpath = os.path.relpath(path, self._top_level_dir) assert not os.path.isabs(_relpath), "Path must be within the project" @@ -254,11 +263,11 @@ class TestLoader(object): yield _make_failed_import_test(name, self.suiteClass) else: mod_file = os.path.abspath(getattr(module, '__file__', full_path)) - realpath = os.path.splitext(mod_file)[0] - fullpath_noext = os.path.splitext(full_path)[0] + realpath = _jython_aware_splitext(mod_file) + fullpath_noext = _jython_aware_splitext(full_path) if realpath.lower() != fullpath_noext.lower(): module_dir = os.path.dirname(realpath) - mod_name = os.path.splitext(os.path.basename(full_path))[0] + mod_name = _jython_aware_splitext(os.path.basename(full_path)) expected_dir = os.path.dirname(full_path) msg = ("%r module incorrectly imported from %r. Expected %r. " "Is this module globally installed?") @@ -287,7 +296,7 @@ class TestLoader(object): else: try: yield load_tests(self, tests, pattern) - except Exception, e: + except Exception as e: yield _make_failed_load_tests(package.__name__, e, self.suiteClass) @@ -302,13 +311,15 @@ def _makeLoader(prefix, sortUsing, suiteClass=None): loader.suiteClass = suiteClass return loader -def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp): +def getTestCaseNames(testCaseClass, prefix, sortUsing=util.three_way_cmp): return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass) -def makeSuite(testCaseClass, prefix='test', sortUsing=cmp, +def makeSuite(testCaseClass, prefix='test', sortUsing=util.three_way_cmp, suiteClass=suite.TestSuite): - return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass) + return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase( + testCaseClass) -def findTestCases(module, prefix='test', sortUsing=cmp, +def findTestCases(module, prefix='test', sortUsing=util.three_way_cmp, suiteClass=suite.TestSuite): - return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module) + return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(\ + module) |