def configureWhere(self, where): """Configure the working directory or directories for the test run. """ from nose.importer import add_path self.workingDir = None where = tolist(where) warned = False for path in where: if not self.workingDir: abs_path = absdir(path) if abs_path is None: raise ValueError("Working directory %s not found, or " "not a directory" % path) log.info("Set working dir to %s", abs_path) self.workingDir = abs_path if self.addPaths and \ os.path.exists(os.path.join(abs_path, '__init__.py')): log.info("Working directory %s is a package; " "adding to sys.path" % abs_path) add_path(abs_path) continue if not warned: warn( "Use of multiple -w arguments is deprecated and " "support may be removed in a future release. You can " "get the same behavior by passing directories without " "the -w argument on the command line, or by using the " "--tests argument in a configuration file.", DeprecationWarning) warned = True self.testNames.append(path)
def configureWhere(self, where): """Configure the working directory or directories for the test run. """ from nose.importer import add_path self.workingDir = None where = tolist(where) warned = False for path in where: if not self.workingDir: abs_path = absdir(path) if abs_path is None: raise ValueError("Working directory %s not found, or " "not a directory" % path) log.info("Set working dir to %s", abs_path) self.workingDir = abs_path if self.addPaths and \ os.path.exists(os.path.join(abs_path, '__init__.py')): log.info("Working directory %s is a package; " "adding to sys.path" % abs_path) add_path(abs_path) continue if not warned: warn("Use of multiple -w arguments is deprecated and " "support may be removed in a future release. You can " "get the same behavior by passing directories without " "the -w argument on the command line, or by using the " "--tests argument in a configuration file.", DeprecationWarning) self.testNames.append(path)
def begin(self): """Create the test database and schema, if needed, and switch the connection over to that database. Then call install() to install all apps listed in the loaded settings module. """ global SETTINGS_PATH # Add the working directory (and any package parents) to sys.path # before trying to import django modules; otherwise, they won't be # able to find project.settings if the working dir is project/ or # project/.. if self.options.django_settings_path: SETTINGS_PATH = self.options.django_settings_path if not SETTINGS_PATH: sys.stderr.write("Can't find Django settings file!\n") # short circuit if no settings file can be found return if self.conf.addPaths: map(add_path, self.conf.where) add_path(SETTINGS_PATH) sys.path.append(SETTINGS_PATH) import settings # Some Django code paths evaluate differently # between DEBUG and not DEBUG. Example of this include the url # dispatcher when 404's are hit. Django's own test runner forces DEBUG # to be off. settings.DEBUG = False from django.core import mail self.mail = mail from django.conf import settings from django.core import management from django.test.utils import setup_test_environment from django.db import connection self.old_db = settings.DATABASE_NAME # setup the test env for each test case setup_test_environment() connection.creation.create_test_db(verbosity=self.verbosity)
def begin(self): """Create the test database and schema, if needed, and switch the connection over to that database. Then call install() to install all apps listed in the loaded settings module. """ # Add the working directory (and any package parents) to sys.path # before trying to import django modules; otherwise, they won't be # able to find project.settings if the working dir is project/ or # project/.. if not SETTINGS_PATH: sys.stderr.write("Can't find Django settings file!\n") # short circuit if no settings file can be found return if self.conf.addPaths: map(add_path, self.conf.where) add_path(SETTINGS_PATH) sys.path.append(SETTINGS_PATH) import settings # Some Django code paths evaluate differently # between DEBUG and not DEBUG. Example of this include the url # dispatcher when 404's are hit. Django's own test runner forces DEBUG # to be off. settings.DEBUG = False from django.core import mail self.mail = mail from django.conf import settings from django.core import management from django.core.management import call_command from django.test.utils import setup_test_environment from django.db import connection self.old_db = settings.DATABASE_NAME # setup the test env for each test case setup_test_environment() connection.creation.create_test_db(verbosity=self.verbosity, autoclobber=self.django_clobber_test_db) if 'south' in settings.INSTALLED_APPS: call_command(name='migrate', verbosity=self.verbosity)
def __init__(self, config=None, importer=None, workingDir=None, selector=None): """Initialize a test loader. Parameters (all optional): * config: provide a `nose.config.Config`_ or other config class instance; if not provided a `nose.config.Config`_ with default values is used. * importer: provide an importer instance that implements `importFromPath`. If not provided, a `nose.importer.Importer`_ is used. * workingDir: the directory to which file and module names are relative. If not provided, assumed to be the current working directory. * selector: a selector class or instance. If a class is provided, it will be instantiated with one argument, the current config. If not provided, a `nose.selector.Selector`_ is used. """ if config is None: config = Config() if importer is None: importer = Importer(config=config) if workingDir is None: workingDir = config.workingDir if selector is None: selector = defaultSelector(config) elif isclass(selector): selector = selector(config) self.config = config self.importer = importer self.workingDir = op_normpath(op_abspath(workingDir)) self.selector = selector if config.addPaths: add_path(workingDir, config) self.suiteClass = ContextSuiteFactory(config=config) self._visitedPaths = set([]) unittest.TestLoader.__init__(self)
def loadTestsFromDir(self, dirname, module=None, importPath=None): """Find tests in a directory. Each item in the directory is tested against self.selector, wantFile or wantDirectory as appropriate. Those that are wanted are returned. """ log.info("%s load tests in %s [%s]", self, dirname, module) if dirname is None: return if not os.path.isabs(dirname): raise ValueError("Dir paths must be specified as " "absolute paths (%s)" % dirname) self.conf.working_dir = dirname # Ensure that any directory we examine is on sys.path if self.conf.addPaths: add_path(dirname) # to ensure that lib paths are set up correctly before tests are # run, examine directories that look like lib or module # directories first and tests last def test_last(a, b, m=self.conf.testMatch): if m.search(a) and not m.search(b): return 1 elif m.search(b) and not m.search(a): return -1 return cmp(a, b) entries = os.listdir(dirname) entries.sort(test_last) for item in entries: tests = None log.debug("candidate %s in %s", item, dirname) path = os.path.join(dirname, item) for test in self.loadTestsFromName(path, module=module, importPath=importPath): yield test
def begin(self): if not SETTINGS_PATH: sys.stderr.write("Can't find Django settings file!\n") return if self.conf.addPaths: map(add_path, self.conf.where) add_path(SETTINGS_PATH) sys.path.insert(0, SETTINGS_PATH) from django.conf import settings settings.DEBUG = False from django.core import mail self.mail = mail from django.test.utils import setup_test_environment # setup the test env for each test case setup_test_environment() # create the database from django.core.management import call_command call_command('syncdb')
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. """ 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) entries.sort(lambda a, b: match_last(a, b, 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() if entry.endswith('.py'): yield self.loadTestsFromName( entry_path, discovered=True) else: yield self.loadTestsFromFile(entry_path) 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: map(remove_path, paths_added) plugins.afterDirectory(path)
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. """ 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) # Python 3.3 now implements PEP 420: Implicit Namespace Packages. # As a result, it's now possible that parent paths that have a # segment with the same basename as our package ends up # in module.__path__. So we have to keep track of what we've # visited, and not-revisit them again. if wanted and not self._haveVisited(entry_path): self._addVisitedPath(entry_path) if is_file: plugins.beforeContext() if entry.endswith('.py'): yield self.loadTestsFromName( entry_path, discovered=True) else: yield self.loadTestsFromFile(entry_path) 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)
def begin(self): """ Create the test database and schema, if needed, and switch the connection over to that database. Then call install() to install all apps listed in the loaded settings module. """ for plugin in self.nose_config.plugins.plugins: if getattr(plugin, 'django_plugin', False): self.django_plugins.append(plugin) os.environ['DJANGO_SETTINGS_MODULE'] = self.settings_module if self.conf.addPaths: map(add_path, self.conf.where) try: __import__(self.settings_module) self.settings_path = self.settings_module except ImportError: # Settings module is not found in PYTHONPATH. Try to do # some funky backwards crawling in directory tree, ie. add # the working directory (and any package parents) to # sys.path before trying to import django modules; # otherwise, they won't be able to find project.settings # if the working dir is project/ or project/.. self.settings_path = get_settings_path(self.settings_module) if not self.settings_path: # short circuit if no settings file can be found raise RuntimeError("Can't find Django settings file!") add_path(self.settings_path) sys.path.append(self.settings_path) from django.conf import settings # Some Django code paths evaluate differently # between DEBUG and not DEBUG. Example of this include the url # dispatcher when 404's are hit. Django's own test runner forces DEBUG # to be off. settings.DEBUG = False self.call_plugins_method('beforeConnectionSetup', settings) from django.core import management from django.test.utils import setup_test_environment self.old_db = settings.DATABASES['default']['NAME'] from django.db import connection self.call_plugins_method( 'beforeTestSetup', settings, setup_test_environment, connection) setup_test_environment() self.call_plugins_method('afterTestSetup', settings) management.get_commands() management._commands['syncdb'] = 'django.core' self.call_plugins_method( 'beforeTestDb', settings, connection, management) connection.creation.create_test_db(verbosity=self.verbosity) self.call_plugins_method('afterTestDb', settings, connection)
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. """ 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) # Python 3.3 now implements PEP 420: Implicit Namespace Packages. # As a result, it's now possible that parent paths that have a # segment with the same basename as our package ends up # in module.__path__. So we have to keep track of what we've # visited, and not-revisit them again. if wanted and not self._haveVisited(entry_path): self._addVisitedPath(entry_path) if is_file: plugins.beforeContext() if entry.endswith('.py'): yield self.loadTestsFromName(entry_path, discovered=True) else: yield self.loadTestsFromFile(entry_path) 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)
def begin(self): """ Create the test database and schema, if needed, and switch the connection over to that database. Then call install() to install all apps listed in the loaded settings module. """ os.environ['DJANGO_SETTINGS_MODULE'] = self.settings_module if self.conf.addPaths: map(add_path, self.conf.where) try: __import__(self.settings_module) self.settings_path = self.settings_module except ImportError: # Settings module is not found in PYTHONPATH. Try to do # some funky backwards crawling in directory tree, ie. add # the working directory (and any package parents) to # sys.path before trying to import django modules; # otherwise, they won't be able to find project.settings # if the working dir is project/ or project/.. self.settings_path = get_settings_path(self.settings_module) if not self.settings_path: # short circuit if no settings file can be found raise RuntimeError("Can't find Django settings file!") add_path(self.settings_path) sys.path.append(self.settings_path) from django.conf import settings # If the user passed in --django-sqlite, use an in-memory sqlite db if self._use_sqlite: settings.DATABASE_ENGINE = 'sqlite3' settings.DATABASE_NAME = '' # in-memory database settings.DATABASE_OPTIONS = {} settings.DATABASE_USER = '' settings.DATABASE_PASSWORD = '' # Do our custom testrunner stuff custom_before(use_testfs=self._use_testfs) # Some Django code paths evaluate differently # between DEBUG and not DEBUG. Example of this include the url # dispatcher when 404's are hit. Django's own test runner forces DEBUG # to be off. settings.DEBUG = False from django.core import management from django.test.utils import setup_test_environment self.old_db = settings.DATABASE_NAME from django.db import connection setup_test_environment() management.get_commands() management._commands['syncdb'] = 'django.core' connection.creation.create_test_db(verbosity=self.verbosity)
def begin(self): """ Create the test database and schema, if needed, and switch the connection over to that database. Then call install() to install all apps listed in the loaded settings module. """ for plugin in self.nose_config.plugins.plugins: if getattr(plugin, 'django_plugin', False): self.django_plugins.append(plugin) os.environ['DJANGO_SETTINGS_MODULE'] = self.settings_module if self.conf.addPaths: map(add_path, self.conf.where) try: __import__(self.settings_module) self.settings_path = self.settings_module except ImportError: # Settings module is not found in PYTHONPATH. Try to do # some funky backwards crawling in directory tree, ie. add # the working directory (and any package parents) to # sys.path before trying to import django modules; # otherwise, they won't be able to find project.settings # if the working dir is project/ or project/.. self.settings_path = get_settings_path(self.settings_module) if not self.settings_path: # short circuit if no settings file can be found raise RuntimeError("Can't find Django settings file!") add_path(self.settings_path) sys.path.append(self.settings_path) from django.conf import settings # Some Django code paths evaluate differently # between DEBUG and not DEBUG. Example of this include the url # dispatcher when 404's are hit. Django's own test runner forces DEBUG # to be off. settings.DEBUG = False self.call_plugins_method('beforeConnectionSetup', settings) from django.core import management from django.test.utils import setup_test_environment if hasattr(settings, 'DATABASES'): self.old_db = settings.DATABASES['default']['NAME'] else: self.old_db = settings.DATABASE_NAME from django.db import connections self._monkeypatch_test_classes() for connection in connections.all(): self.call_plugins_method('beforeTestSetup', settings, setup_test_environment, connection) setup_test_environment() import django if hasattr(django, 'setup'): django.setup() self.call_plugins_method('afterTestSetup', settings) management.get_commands() # Ensure that nothing (eg. South) steals away our syncdb command if self.django_version < self.DJANGO_1_7: management._commands['syncdb'] = 'django.core' for connection in connections.all(): self.call_plugins_method('beforeTestDb', settings, connection, management) connection.creation.create_test_db( verbosity=self.verbosity, autoclobber=True, ) logger.debug("Running syncdb") self._num_syncdb_calls += 1 self.call_plugins_method('afterTestDb', settings, connection) self.store_original_transaction_methods()
def begin(self): """Create the test database and schema, if needed, and switch the connection over to that database. Then call install() to install all apps listed in the loaded settings module. """ os.environ['DJANGO_SETTINGS_MODULE'] = self.settings_module if self.conf.addPaths: map(add_path, self.conf.where) try: __import__(self.settings_module) self.settings_path = self.settings_module except ImportError: # Settings module is not found in PYTHONPATH. Try to do # some funky backwards crawling in directory tree, ie. add # the working directory (and any package parents) to # sys.path before trying to import django modules; # otherwise, they won't be able to find project.settings # if the working dir is project/ or project/.. self.settings_path = get_settings_path(self.settings_module) if not self.settings_path: # short circuit if no settings file can be found raise RuntimeError("Can't find Django settings file!") add_path(self.settings_path) sys.path.append(self.settings_path) from django.conf import settings # Some Django code paths evaluate differently # between DEBUG and not DEBUG. Example of this include the url # dispatcher when 404's are hit. Django's own test runner forces DEBUG # to be off. settings.DEBUG = False from django.core import management from django.test.utils import setup_test_environment self.old_db = settings.DATABASE_NAME from django.db import connection if 'south' in settings.INSTALLED_APPS: # South has its own test command that turns off migrations # during testings. If we detected south, we need to fix syncdb. management.get_commands() management._commands['syncdb'] = 'django.core' setup_test_environment() # For database creation only, bypass the capture plugin. This # allows the user to interact with the "test database already # exists" message. old_stdout = sys.stdout sys.stdout = sys.__stdout__ try: connection.creation.create_test_db(verbosity=self.verbosity) finally: sys.stdout = old_stdout
def importFromDir(self, dir, fqname): """Import a module *only* from path, ignoring sys.path and reloading if the version in sys.modules is not the one we want. """ dir = os.path.normpath(os.path.abspath(dir)) log.debug("Import %s from %s", fqname, dir) # FIXME reimplement local per-dir cache? # special case for __main__ if fqname == '__main__': return sys.modules[fqname] if self.config.addPaths: add_path(dir, self.config) path = [dir] parts = fqname.split('.') part_fqname = '' mod = parent = fh = None for part in parts: if part_fqname == '': part_fqname = part else: part_fqname = "%s.%s" % (part_fqname, part) try: acquire_lock() log.debug("find module part %s (%s) in %s", part, part_fqname, path) fh, filename, desc = find_module(part, path) old = sys.modules.get(part_fqname) # start Odoo specific part odoo_fqname = 'openerp.addons.%s' % part_fqname odoo_old = sys.modules.get(odoo_fqname) odoo_module_fqname = 'openerp.addons.%s' % part_fqname.split( '.')[0] odoo_module_old = sys.modules.get(odoo_module_fqname) # end Odoo specific part if old is not None: # test modules frequently have name overlap; make sure # we get a fresh copy of anything we are trying to load # from a new path log.debug("sys.modules has %s as %s", part_fqname, old) if (self.sameModule(old, filename) or (self.config.firstPackageWins and getattr(old, '__path__', None))): mod = old else: del sys.modules[part_fqname] mod = load_module(part_fqname, fh, filename, desc) # start Odoo specific part elif odoo_old: # Module already imported by openerp mod = sys.modules[part_fqname] = odoo_old elif odoo_module_old: # Module not imported by openerp mod = sys.modules[part_fqname] = load_module( 'openerp.addons.' + part_fqname, fh, filename, desc) # end Odoo specific part else: mod = load_module(part_fqname, fh, filename, desc) finally: if fh: fh.close() release_lock() if parent: setattr(parent, part, mod) if hasattr(mod, '__path__'): path = mod.__path__ parent = mod return mod
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. """ 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) entries.sort(lambda a, b: match_last(a, b, self.config.testMatch)) for entry in entries: if entry.startswith('.') or 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: wanted = self.selector.wantDirectory(entry_path) is_package = ispackage(entry_path) if wanted: if is_file: plugins.beforeContext() if entry.endswith('.py'): yield self.loadTestsFromName( entry_path, discovered=True) else: yield self.loadTestsFromFile(entry_path) 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)) # Catch TypeError and AttributeError exceptions here and discard # them: the default plugin manager, NoPlugins, will raise TypeError # on generative calls. try: tests = [] for test in plugins.loadTestsFromDir(path): tests.append(test) yield self.suiteClass(tests) except (TypeError, AttributeError): pass except (KeyboardInterrupt, SystemExit): raise except: yield self.suiteClass([Failure(*sys.exc_info())]) # pop paths if self.config.addPaths: map(remove_path, paths_added) plugins.afterDirectory(path)