def loadTestsFromModule(self, module, path=None, discovered=False): """Load all tests from module and return a suite containing them. If the module has been discovered and is not test-like, the suite will be empty by default, though plugins may add their own tests. """ log.debug("Load from module %s", module) tests = [] test_classes = [] test_funcs = [] # For *discovered* modules, we only load tests when the module looks # testlike. For modules we've been directed to load, we always # look for tests. (discovered is set to True by loadTestsFromDir) if not discovered or self.selector.wantModule(module): for item in dir(module): test = getattr(module, item, None) # print "Check %s (%s) in %s" % (item, test, module.__name__) if isclass(test): if self.selector.wantClass(test): test_classes.append(test) elif isfunction(test) and self.selector.wantFunction(test): test_funcs.append(test) sort_list(test_classes, lambda x: x.__name__) sort_list(test_funcs, func_lineno) tests = map(lambda t: self.makeTest(t, parent=module), test_classes + test_funcs) # Now, descend into packages # FIXME can or should this be lazy? # is this syntax 2.2 compatible? module_paths = getattr(module, '__path__', []) if path: path = os.path.realpath(path) for module_path in module_paths: log.debug("Load tests from module path %s?", module_path) log.debug("path: %s os.path.realpath(%s): %s", path, module_path, os.path.realpath(module_path)) # BEGIN MONKEYPATCH #If a path was passed in, the case of path and #module_path need to be normalized before comparing the two. #This is to resolve a Windows-only issue with tests not being #discovered correctly for namespace packages. if path: norm_module_path = os.path.normcase(module_path) norm_path = os.path.normcase(path) # END MONKEYPATCH if (self.config.traverseNamespace or not path) or \ os.path.realpath(norm_module_path).startswith(norm_path): # Egg files can be on sys.path, so make sure the path is a # directory before trying to load from it. if os.path.isdir(module_path): tests.extend(self.loadTestsFromDir(module_path)) for test in self.config.plugins.loadTestsFromModule(module, path): tests.append(test) return self.suiteClass(ContextList(tests, context=module))
def loadTestsFromDir(self, path): """Load tests from the directory at path. This is a generator -- each suite of tests from a module or other file is yielded and is expected to be executed before the next file is examined. """ from nose.loader import (log, add_path, op_abspath, op_isfile, op_isdir, Failure, remove_path, sort_list, regex_last_key, op_join, ispackage) log.debug("load from dir %s", path) plugins = self.config.plugins plugins.beforeDirectory(path) if self.config.addPaths: paths_added = add_path(path, self.config) entries = os.listdir(path) sort_list(entries, regex_last_key(self.config.testMatch)) for entry in entries: # this hard-coded initial-dot test will be removed: # http://code.google.com/p/python-nose/issues/detail?id=82 if entry.startswith('.'): continue entry_path = op_abspath(op_join(path, entry)) is_file = op_isfile(entry_path) wanted = False if is_file: is_dir = False wanted = self.selector.wantFile(entry_path) else: is_dir = op_isdir(entry_path) if is_dir: # this hard-coded initial-underscore test will be removed: # http://code.google.com/p/python-nose/issues/detail?id=82 if entry.startswith('_'): continue wanted = self.selector.wantDirectory(entry_path) is_package = ispackage(entry_path) if wanted: if is_file: plugins.beforeContext() ### Identifying Python files: ################################# # # if '.py' in entry[-4:]: yield self.loadTestsFromName( entry_path, discovered=True) else: yield self.loadTestsFromFile(entry_path) # # ### Finished identifying Python files. ######################## plugins.afterContext() elif is_package: # Load the entry as a package: given the full path, # loadTestsFromName() will figure it out yield self.loadTestsFromName( entry_path, discovered=True) else: # Another test dir in this one: recurse lazily yield self.suiteClass( lambda: self.loadTestsFromDir(entry_path)) tests = [] for test in plugins.loadTestsFromDir(path): tests.append(test) # TODO: is this try/except needed? try: if tests: yield self.suiteClass(tests) except (KeyboardInterrupt, SystemExit): raise except: yield self.suiteClass([Failure(*sys.exc_info())]) # pop paths if self.config.addPaths: for p in paths_added: remove_path(p) plugins.afterDirectory(path)