]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- remove some crufty old testing options
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 15 Sep 2014 01:41:13 +0000 (21:41 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 15 Sep 2014 01:41:13 +0000 (21:41 -0400)
- reestablish the "bootstrap" system of loading the test runners
in testing/plugin; using the updated approach we just came up with for
alembic.  Coverage should be fixed now when running either py.test or
nose. fixes #3196
- upgrade tox.ini and start using a .coveragerc file

.coveragerc [new file with mode: 0644]
.gitignore
lib/sqlalchemy/testing/plugin/bootstrap.py [new file with mode: 0644]
lib/sqlalchemy/testing/plugin/noseplugin.py
lib/sqlalchemy/testing/plugin/plugin_base.py
lib/sqlalchemy/testing/plugin/pytestplugin.py
lib/sqlalchemy/testing/provision.py [moved from lib/sqlalchemy/testing/plugin/provision.py with 98% similarity]
lib/sqlalchemy/testing/runner.py
sqla_nose.py
test/conftest.py
tox.ini

diff --git a/.coveragerc b/.coveragerc
new file mode 100644 (file)
index 0000000..5d6c2bd
--- /dev/null
@@ -0,0 +1,5 @@
+[run]
+include=lib/sqlalchemy/*
+
+[report]
+omit=lib/sqlalchemy/testing/*
\ No newline at end of file
index c22e53c39043613ba22428f057f385d204bfe790..55066f84370acb6e8122ab3a79a7dc1a6485a769 100644 (file)
@@ -6,10 +6,12 @@
 /doc/build/output/
 /dogpile_data/
 *.orig
+*,cover
 /.tox
 .venv
 *.egg-info
 .coverage
+coverage.xml
 .*,cover
 *.class
 *.so
diff --git a/lib/sqlalchemy/testing/plugin/bootstrap.py b/lib/sqlalchemy/testing/plugin/bootstrap.py
new file mode 100644 (file)
index 0000000..497fcb7
--- /dev/null
@@ -0,0 +1,44 @@
+"""
+Bootstrapper for nose/pytest plugins.
+
+The entire rationale for this system is to get the modules in plugin/
+imported without importing all of the supporting library, so that we can
+set up things for testing before coverage starts.
+
+The rationale for all of plugin/ being *in* the supporting library in the
+first place is so that the testing and plugin suite is available to other
+libraries, mainly external SQLAlchemy and Alembic dialects, to make use
+of the same test environment and standard suites available to
+SQLAlchemy/Alembic themselves without the need to ship/install a separate
+package outside of SQLAlchemy.
+
+NOTE:  copied/adapted from SQLAlchemy master for backwards compatibility;
+this should be removable when Alembic targets SQLAlchemy 1.0.0.
+
+"""
+
+import os
+import sys
+
+bootstrap_file = locals()['bootstrap_file']
+to_bootstrap = locals()['to_bootstrap']
+
+
+def load_file_as_module(name):
+    path = os.path.join(os.path.dirname(bootstrap_file), "%s.py" % name)
+    if sys.version_info >= (3, 3):
+        from importlib import machinery
+        mod = machinery.SourceFileLoader(name, path).load_module()
+    else:
+        import imp
+        mod = imp.load_source(name, path)
+    return mod
+
+if to_bootstrap == "pytest":
+    sys.modules["sqla_plugin_base"] = load_file_as_module("plugin_base")
+    sys.modules["sqla_pytestplugin"] = load_file_as_module("pytestplugin")
+elif to_bootstrap == "nose":
+    sys.modules["sqla_plugin_base"] = load_file_as_module("plugin_base")
+    sys.modules["sqla_noseplugin"] = load_file_as_module("noseplugin")
+else:
+    raise Exception("unknown bootstrap: %s" % to_bootstrap)  # noqa
index 6ef539142c22e3bfd3a71695a5a1227a600946e5..eb4a3b258889331515eb23fa0a7dd79c1a2be2f1 100644 (file)
@@ -12,6 +12,14 @@ way (e.g. as a package-less import).
 
 """
 
+try:
+    # installed by bootstrap.py
+    import sqla_plugin_base as plugin_base
+except ImportError:
+    # assume we're a package, use traditional import
+    from . import plugin_base
+
+
 import os
 import sys
 
@@ -19,16 +27,6 @@ from nose.plugins import Plugin
 fixtures = None
 
 py3k = sys.version_info >= (3, 0)
-# no package imports yet!  this prevents us from tripping coverage
-# too soon.
-path = os.path.join(os.path.dirname(__file__), "plugin_base.py")
-if sys.version_info >= (3, 3):
-    from importlib import machinery
-    plugin_base = machinery.SourceFileLoader(
-        "plugin_base", path).load_module()
-else:
-    import imp
-    plugin_base = imp.load_source("plugin_base", path)
 
 
 class NoseSQLAlchemy(Plugin):
@@ -58,10 +56,10 @@ class NoseSQLAlchemy(Plugin):
 
         plugin_base.set_coverage_flag(options.enable_plugin_coverage)
 
+    def begin(self):
         global fixtures
-        from sqlalchemy.testing import fixtures
+        from sqlalchemy.testing import fixtures  # noqa
 
-    def begin(self):
         plugin_base.post_begin()
 
     def describeTest(self, test):
@@ -72,19 +70,21 @@ class NoseSQLAlchemy(Plugin):
 
     def wantMethod(self, fn):
         if py3k:
+            if not hasattr(fn.__self__, 'cls'):
+                return False
             cls = fn.__self__.cls
         else:
             cls = fn.im_class
-        print "METH:", fn, "CLS:", cls
         return plugin_base.want_method(cls, fn)
 
     def wantClass(self, cls):
         return plugin_base.want_class(cls)
 
     def beforeTest(self, test):
-        plugin_base.before_test(test,
-                                test.test.cls.__module__,
-                                test.test.cls, test.test.method.__name__)
+        plugin_base.before_test(
+            test,
+            test.test.cls.__module__,
+            test.test.cls, test.test.method.__name__)
 
     def afterTest(self, test):
         plugin_base.after_test(test)
index 7ba31d3e360bdb808118e7a19aa972610f6af1f6..6696427dcfa36f48fcf322fefb7d45d8fad61d61 100644 (file)
@@ -31,8 +31,6 @@ if py3k:
 else:
     import ConfigParser as configparser
 
-FOLLOWER_IDENT = None
-
 # late imports
 fixtures = None
 engines = None
@@ -72,8 +70,6 @@ def setup_options(make_option):
                 help="Drop all tables in the target database first")
     make_option("--backend-only", action="store_true", dest="backend_only",
                 help="Run only tests marked with __backend__")
-    make_option("--mockpool", action="store_true", dest="mockpool",
-                help="Use mock pool (asserts only one connection used)")
     make_option("--low-connections", action="store_true",
                 dest="low_connections",
                 help="Use a low number of distinct connections - "
@@ -95,14 +91,6 @@ def setup_options(make_option):
     make_option("--exclude-tag", action="callback", callback=_exclude_tag,
                 type="string",
                 help="Exclude tests with tag <tag>")
-    make_option("--serverside", action="store_true",
-                help="Turn on server side cursors for PG")
-    make_option("--mysql-engine", action="store",
-                dest="mysql_engine", default=None,
-                help="Use the specified MySQL storage engine for all tables, "
-                "default is a db-default/InnoDB combo.")
-    make_option("--tableopts", action="append", dest="tableopts", default=[],
-                help="Add a dialect-specific table option, key=value")
     make_option("--write-profiles", action="store_true",
                 dest="write_profiles", default=False,
                 help="Write/update profiling data.")
@@ -115,8 +103,8 @@ def configure_follower(follower_ident):
     database creation.
 
     """
-    global FOLLOWER_IDENT
-    FOLLOWER_IDENT = follower_ident
+    from sqlalchemy.testing import provision
+    provision.FOLLOWER_IDENT = follower_ident
 
 
 def memoize_important_follower_config(dict_):
@@ -177,12 +165,14 @@ def post_begin():
     global util, fixtures, engines, exclusions, \
         assertions, warnings, profiling,\
         config, testing
-    from sqlalchemy import testing
-    from sqlalchemy.testing import fixtures, engines, exclusions, \
-        assertions, warnings, profiling, config
-    from sqlalchemy import util
+    from sqlalchemy import testing # noqa
+    from sqlalchemy.testing import fixtures, engines, exclusions  # noqa
+    from sqlalchemy.testing import assertions, warnings, profiling # noqa
+    from sqlalchemy.testing import config  # noqa
+    from sqlalchemy import util  # noqa
     warnings.setup_filters()
 
+
 def _log(opt_str, value, parser):
     global logging
     if not logging:
@@ -233,12 +223,6 @@ def _setup_options(opt, file_config):
     options = opt
 
 
-@pre
-def _server_side_cursors(options, file_config):
-    if options.serverside:
-        db_opts['server_side_cursors'] = True
-
-
 @pre
 def _monkeypatch_cdecimal(options, file_config):
     if options.cdecimal:
@@ -250,7 +234,7 @@ def _monkeypatch_cdecimal(options, file_config):
 def _engine_uri(options, file_config):
     from sqlalchemy.testing import config
     from sqlalchemy import testing
-    from sqlalchemy.testing.plugin import provision
+    from sqlalchemy.testing import provision
 
     if options.dburi:
         db_urls = list(options.dburi)
@@ -273,19 +257,12 @@ def _engine_uri(options, file_config):
 
     for db_url in db_urls:
         cfg = provision.setup_config(
-            db_url, db_opts, options, file_config, FOLLOWER_IDENT)
+            db_url, db_opts, options, file_config, provision.FOLLOWER_IDENT)
 
         if not config._current:
             cfg.set_as_current(cfg, testing)
 
 
-@post
-def _engine_pool(options, file_config):
-    if options.mockpool:
-        from sqlalchemy import pool
-        db_opts['poolclass'] = pool.AssertionPool
-
-
 @post
 def _requirements(options, file_config):
 
@@ -368,19 +345,6 @@ def _prep_testing_database(options, file_config):
                             schema=enum['schema'])))
 
 
-@post
-def _set_table_options(options, file_config):
-    from sqlalchemy.testing import schema
-
-    table_options = schema.table_options
-    for spec in options.tableopts:
-        key, value = spec.split('=')
-        table_options[key] = value
-
-    if options.mysql_engine:
-        table_options['mysql_engine'] = options.mysql_engine
-
-
 @post
 def _reverse_topological(options, file_config):
     if options.reversetop:
index 005942913306ff15adaa6dfe062637dcd2ef4661..4bbc8ed9a2ea2f1f6c22808748dba24af5a09141 100644 (file)
@@ -1,7 +1,13 @@
+try:
+    # installed by bootstrap.py
+    import sqla_plugin_base as plugin_base
+except ImportError:
+    # assume we're a package, use traditional import
+    from . import plugin_base
+
 import pytest
 import argparse
 import inspect
-from . import plugin_base
 import collections
 import itertools
 
@@ -42,6 +48,8 @@ def pytest_configure(config):
     plugin_base.set_coverage_flag(bool(getattr(config.option,
                                                "cov_source", False)))
 
+
+def pytest_sessionstart(session):
     plugin_base.post_begin()
 
 if has_xdist:
@@ -54,11 +62,11 @@ if has_xdist:
         plugin_base.memoize_important_follower_config(node.slaveinput)
 
         node.slaveinput["follower_ident"] = "test_%s" % next(_follower_count)
-        from . import provision
+        from sqlalchemy.testing import provision
         provision.create_follower_db(node.slaveinput["follower_ident"])
 
     def pytest_testnodedown(node, error):
-        from . import provision
+        from sqlalchemy.testing import provision
         provision.drop_follower_db(node.slaveinput["follower_ident"])
 
 
similarity index 98%
rename from lib/sqlalchemy/testing/plugin/provision.py
rename to lib/sqlalchemy/testing/provision.py
index c6b9030f57818938c362a4c900924c33ccda3b43..0bcdad9594df5ee5b7c10ded7f48109db3d167c5 100644 (file)
@@ -1,8 +1,10 @@
 from sqlalchemy.engine import url as sa_url
 from sqlalchemy import text
 from sqlalchemy.util import compat
-from .. import config, engines
-import os
+from . import config, engines
+
+
+FOLLOWER_IDENT = None
 
 
 class register(object):
index df254520b87039b83aedd6958b180aa6cf5124d8..23d7a0a912c457608019d98ee8abba94c1ae4351 100644 (file)
@@ -30,7 +30,7 @@ SQLAlchemy itself is possible.
 
 """
 
-from sqlalchemy.testing.plugin.noseplugin import NoseSQLAlchemy
+from .plugin.noseplugin import NoseSQLAlchemy
 
 import nose
 
index f89a1dce06662c72f782d4a8dc36b3b7e899a52b..b977f4bf56e9b5d5e4738ad503150c465eac0e04 100755 (executable)
@@ -8,22 +8,25 @@ installs SQLAlchemy's testing plugin into the local environment.
 """
 import sys
 import nose
-import warnings
+import os
 
 
-from os import path
 for pth in ['./lib']:
-    sys.path.insert(0, path.join(path.dirname(path.abspath(__file__)), pth))
+    sys.path.insert(
+        0, os.path.join(os.path.dirname(os.path.abspath(__file__)), pth))
 
-# installing without importing SQLAlchemy, so that coverage includes
-# SQLAlchemy itself.
-path = "lib/sqlalchemy/testing/plugin/noseplugin.py"
-if sys.version_info >= (3, 3):
-    from importlib import machinery
-    noseplugin = machinery.SourceFileLoader("noseplugin", path).load_module()
-else:
-    import imp
-    noseplugin = imp.load_source("noseplugin", path)
+# use bootstrapping so that test plugins are loaded
+# without touching the main library before coverage starts
+bootstrap_file = os.path.join(
+    os.path.dirname(__file__), "lib", "sqlalchemy",
+    "testing", "plugin", "bootstrap.py"
+)
 
+with open(bootstrap_file) as f:
+    code = compile(f.read(), "bootstrap.py", 'exec')
+    to_bootstrap = "nose"
+    exec(code, globals(), locals())
 
-nose.main(addplugins=[noseplugin.NoseSQLAlchemy()])
+
+from noseplugin import NoseSQLAlchemy
+nose.main(addplugins=[NoseSQLAlchemy()])
index 1dd442309955e451e7fdbc4e6413186ad94be8e3..c697085ee9c5923dd8f3ddd666d0db472496d8cc 100755 (executable)
@@ -7,9 +7,23 @@ installs SQLAlchemy's testing plugin into the local environment.
 
 """
 import sys
+import os
 
-from os import path
 for pth in ['../lib']:
-    sys.path.insert(0, path.join(path.dirname(path.abspath(__file__)), pth))
+    sys.path.insert(
+        0,
+        os.path.join(os.path.dirname(os.path.abspath(__file__)), pth))
 
-from sqlalchemy.testing.plugin.pytestplugin import *
+
+# use bootstrapping so that test plugins are loaded
+# without touching the main library before coverage starts
+bootstrap_file = os.path.join(
+    os.path.dirname(__file__), "..", "lib", "sqlalchemy",
+    "testing", "plugin", "bootstrap.py"
+)
+
+with open(bootstrap_file) as f:
+    code = compile(f.read(), "bootstrap.py", 'exec')
+    to_bootstrap = "pytest"
+    exec(code, globals(), locals())
+    from pytestplugin import *  # noqa
diff --git a/tox.ini b/tox.ini
index 304bfd632c400144cc062db7b205b3992ccc7095..46ac122beac36ca8f874a0050681a612f7401964 100644 (file)
--- a/tox.ini
+++ b/tox.ini
@@ -1,18 +1,15 @@
 [tox]
-envlist = full
+envlist = full,py26,py27,py33,py34
 
 [testenv]
 deps=pytest
-     flake8
-     coverage
      mock
 
 sitepackages=True
 usedevelop=True
 
 commands=
-  python -m pytest {posargs}
-envdir=pytest
+  python -m pytest -n4 {posargs}
 
 [testenv:full]
 
@@ -21,21 +18,22 @@ envdir=pytest
 setenv=
   DISABLE_SQLALCHEMY_CEXT=1
 
+# see also .coveragerc
+deps=coverage
 commands=
-  python -m pytest \
-        --cov=lib/sqlalchemy \
-        --exclude-tag memory-intensive \
-        --exclude-tag timing-intensive \
-        -k "not aaa_profiling" \
-        {posargs}
-  python -m coverage xml --include=lib/sqlalchemy/*
+  python -m pytest --cov=sqlalchemy --cov-report term --cov-report xml \
+    --exclude-tag memory-intensive \
+    --exclude-tag timing-intensive \
+    -k "not aaa_profiling" \
+    {posargs}
+
 
 [testenv:pep8]
 commands = python -m flake8 {posargs}
 
 
 [flake8]
-
+deps=flake8
 show-source = True
 ignore = E711,E712,E721,F841,F811
 exclude=.venv,.git,.tox,dist,doc,*egg,build