diff options
| author | Brian Jarrett <celttechie@gmail.com> | 2014-07-20 12:44:40 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-07-20 12:44:40 -0400 |
| commit | cca03097f47f22783d42d1853faac6cf84607c5a (patch) | |
| tree | 4fe1a63d03a2d88d1cf37e1167759dfaf84f4ce7 /lib/sqlalchemy/testing/plugin | |
| parent | 827329a0cca5351094a1a86b6b2be2b9182f0ae2 (diff) | |
| download | sqlalchemy-cca03097f47f22783d42d1853faac6cf84607c5a.tar.gz | |
- apply pep8 formatting to sqlalchemy/sql, sqlalchemy/util, sqlalchemy/dialects,
sqlalchemy/orm, sqlalchemy/event, sqlalchemy/testing
Diffstat (limited to 'lib/sqlalchemy/testing/plugin')
| -rw-r--r-- | lib/sqlalchemy/testing/plugin/noseplugin.py | 13 | ||||
| -rw-r--r-- | lib/sqlalchemy/testing/plugin/plugin_base.py | 156 | ||||
| -rw-r--r-- | lib/sqlalchemy/testing/plugin/pytestplugin.py | 39 |
3 files changed, 126 insertions, 82 deletions
diff --git a/lib/sqlalchemy/testing/plugin/noseplugin.py b/lib/sqlalchemy/testing/plugin/noseplugin.py index 7262adb4b..e362d6141 100644 --- a/lib/sqlalchemy/testing/plugin/noseplugin.py +++ b/lib/sqlalchemy/testing/plugin/noseplugin.py @@ -21,9 +21,10 @@ fixtures = None # 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): +if sys.version_info >= (3, 3): from importlib import machinery - plugin_base = machinery.SourceFileLoader("plugin_base", path).load_module() + plugin_base = machinery.SourceFileLoader( + "plugin_base", path).load_module() else: import imp plugin_base = imp.load_source("plugin_base", path) @@ -76,20 +77,20 @@ class NoseSQLAlchemy(Plugin): def beforeTest(self, test): plugin_base.before_test(test, - test.test.cls.__module__, - test.test.cls, test.test.method.__name__) + test.test.cls.__module__, + test.test.cls, test.test.method.__name__) def afterTest(self, test): plugin_base.after_test(test) def startContext(self, ctx): if not isinstance(ctx, type) \ - or not issubclass(ctx, fixtures.TestBase): + or not issubclass(ctx, fixtures.TestBase): return plugin_base.start_test_class(ctx) def stopContext(self, ctx): if not isinstance(ctx, type) \ - or not issubclass(ctx, fixtures.TestBase): + or not issubclass(ctx, fixtures.TestBase): return plugin_base.stop_test_class(ctx) diff --git a/lib/sqlalchemy/testing/plugin/plugin_base.py b/lib/sqlalchemy/testing/plugin/plugin_base.py index b91fa4d50..2590f3b1e 100644 --- a/lib/sqlalchemy/testing/plugin/plugin_base.py +++ b/lib/sqlalchemy/testing/plugin/plugin_base.py @@ -8,8 +8,8 @@ """Testing extensions. this module is designed to work as a testing-framework-agnostic library, -so that we can continue to support nose and also begin adding new functionality -via py.test. +so that we can continue to support nose and also begin adding new +functionality via py.test. """ @@ -50,50 +50,62 @@ logging = None db_opts = {} options = None + def setup_options(make_option): make_option("--log-info", action="callback", type="string", callback=_log, - help="turn on info logging for <LOG> (multiple OK)") - make_option("--log-debug", action="callback", type="string", callback=_log, - help="turn on debug logging for <LOG> (multiple OK)") + help="turn on info logging for <LOG> (multiple OK)") + make_option("--log-debug", action="callback", + type="string", callback=_log, + help="turn on debug logging for <LOG> (multiple OK)") make_option("--db", action="append", type="string", dest="db", help="Use prefab database uri. Multiple OK, " - "first one is run by default.") + "first one is run by default.") make_option('--dbs', action='callback', callback=_list_dbs, - help="List available prefab dbs") + help="List available prefab dbs") make_option("--dburi", action="append", type="string", dest="dburi", - help="Database uri. Multiple OK, first one is run by default.") + help="Database uri. Multiple OK, " + "first one is run by default.") make_option("--dropfirst", action="store_true", dest="dropfirst", - help="Drop all tables in the target database first") + 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__") + 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 - i.e. for Oracle TNS" - ) - make_option("--reversetop", action="store_true", dest="reversetop", default=False, - help="Use a random-ordering set implementation in the ORM (helps " - "reveal dependency issues)") + 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 - " + "i.e. for Oracle TNS") + make_option("--reversetop", action="store_true", + dest="reversetop", default=False, + help="Use a random-ordering set implementation in the ORM " + "(helps reveal dependency issues)") make_option("--requirements", action="callback", type="string", - callback=_requirements_opt, - help="requirements class for testing, overrides setup.cfg") - make_option("--with-cdecimal", action="store_true", dest="cdecimal", default=False, - help="Monkeypatch the cdecimal library into Python 'decimal' for all tests") - make_option("--serverside", action="callback", callback=_server_side_cursors, - 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.") + callback=_requirements_opt, + help="requirements class for testing, overrides setup.cfg") + make_option("--with-cdecimal", action="store_true", + dest="cdecimal", default=False, + help="Monkeypatch the cdecimal library into Python 'decimal' " + "for all tests") + make_option("--serverside", action="callback", + callback=_server_side_cursors, + 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.") + 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.") + def read_config(): global file_config file_config = configparser.ConfigParser() file_config.read(['setup.cfg', 'test.cfg']) + def pre_begin(opt): """things to set up early, before coverage might be setup.""" global options @@ -101,9 +113,11 @@ def pre_begin(opt): for fn in pre_configure: fn(options, file_config) + def set_coverage_flag(value): options.has_coverage = value + def post_begin(): """things to set up later, once we know coverage is running.""" # Lazy setup of other options (post coverage) @@ -113,11 +127,11 @@ def post_begin(): # late imports, has to happen after config as well # as nose plugins like coverage global util, fixtures, engines, exclusions, \ - assertions, warnings, profiling,\ - config, testing + assertions, warnings, profiling,\ + config, testing from sqlalchemy import testing from sqlalchemy.testing import fixtures, engines, exclusions, \ - assertions, warnings, profiling, config + assertions, warnings, profiling, config from sqlalchemy import util @@ -143,6 +157,7 @@ def _list_dbs(*args): def _server_side_cursors(opt_str, value, parser): db_opts['server_side_cursors'] = True + def _requirements_opt(opt_str, value, parser): _setup_requirements(value) @@ -189,8 +204,9 @@ def _engine_uri(options, file_config): for db in re.split(r'[,\s]+', db_token): if db not in file_config.options('db'): raise RuntimeError( - "Unknown URI specifier '%s'. Specify --dbs for known uris." - % db) + "Unknown URI specifier '%s'. " + "Specify --dbs for known uris." + % db) else: db_urls.append(file_config.get('db', db)) @@ -211,12 +227,14 @@ def _engine_pool(options, file_config): from sqlalchemy import pool db_opts['poolclass'] = pool.AssertionPool + @post def _requirements(options, file_config): requirement_cls = file_config.get('sqla_testing', "requirement_cls") _setup_requirements(requirement_cls) + def _setup_requirements(argument): from sqlalchemy.testing import config from sqlalchemy import testing @@ -235,6 +253,7 @@ def _setup_requirements(argument): config.requirements = testing.requires = req_cls() + @post def _prep_testing_database(options, file_config): from sqlalchemy.testing import config @@ -250,27 +269,36 @@ def _prep_testing_database(options, file_config): pass else: for vname in view_names: - e.execute(schema._DropView(schema.Table(vname, schema.MetaData()))) + e.execute(schema._DropView( + schema.Table(vname, schema.MetaData()) + )) if config.requirements.schemas.enabled_for_config(cfg): try: - view_names = inspector.get_view_names(schema="test_schema") + view_names = inspector.get_view_names( + schema="test_schema") except NotImplementedError: pass else: for vname in view_names: e.execute(schema._DropView( - schema.Table(vname, - schema.MetaData(), schema="test_schema"))) + schema.Table(vname, schema.MetaData(), + schema="test_schema") + )) - for tname in reversed(inspector.get_table_names(order_by="foreign_key")): - e.execute(schema.DropTable(schema.Table(tname, schema.MetaData()))) + for tname in reversed(inspector.get_table_names( + order_by="foreign_key")): + e.execute(schema.DropTable( + schema.Table(tname, schema.MetaData()) + )) if config.requirements.schemas.enabled_for_config(cfg): for tname in reversed(inspector.get_table_names( - order_by="foreign_key", schema="test_schema")): + order_by="foreign_key", schema="test_schema")): e.execute(schema.DropTable( - schema.Table(tname, schema.MetaData(), schema="test_schema"))) + schema.Table(tname, schema.MetaData(), + schema="test_schema") + )) @post @@ -304,7 +332,7 @@ def _post_setup_options(opt, file_config): def _setup_profiling(options, file_config): from sqlalchemy.testing import profiling profiling._profile_stats = profiling.ProfileStatsFile( - file_config.get('sqla_testing', 'profile_file')) + file_config.get('sqla_testing', 'profile_file')) def want_class(cls): @@ -312,22 +340,24 @@ def want_class(cls): return False elif cls.__name__.startswith('_'): return False - elif config.options.backend_only and not getattr(cls, '__backend__', False): + elif config.options.backend_only and not getattr(cls, '__backend__', + False): return False else: return True + def generate_sub_tests(cls, module): if getattr(cls, '__backend__', False): for cfg in _possible_configs_for_cls(cls): name = "%s_%s_%s" % (cls.__name__, cfg.db.name, cfg.db.driver) subcls = type( - name, - (cls, ), - { - "__only_on__": ("%s+%s" % (cfg.db.name, cfg.db.driver)), - "__backend__": False} - ) + name, + (cls, ), + { + "__only_on__": ("%s+%s" % (cfg.db.name, cfg.db.driver)), + "__backend__": False} + ) setattr(module, name, subcls) yield subcls else: @@ -338,20 +368,24 @@ def start_test_class(cls): _do_skips(cls) _setup_engine(cls) + def stop_test_class(cls): engines.testing_reaper._stop_test_ctx() if not options.low_connections: assertions.global_cleanup_assertions() _restore_engine() + def _restore_engine(): config._current.reset(testing) + def _setup_engine(cls): if getattr(cls, '__engine_options__', None): eng = engines.testing_engine(options=cls.__engine_options__) config._current.push_engine(eng, testing) + def before_test(test, test_module_name, test_class, test_name): # like a nose id, e.g.: @@ -367,10 +401,12 @@ def before_test(test, test_module_name, test_class, test_name): warnings.resetwarnings() profiling._current_test = id_ + def after_test(test): engines.testing_reaper._after_test_ctx() warnings.resetwarnings() + def _possible_configs_for_cls(cls): all_configs = set(config.Config.all_configs()) if cls.__unsupported_on__: @@ -378,16 +414,14 @@ def _possible_configs_for_cls(cls): for config_obj in list(all_configs): if spec(config_obj): all_configs.remove(config_obj) - if getattr(cls, '__only_on__', None): spec = exclusions.db_spec(*util.to_list(cls.__only_on__)) for config_obj in list(all_configs): if not spec(config_obj): all_configs.remove(config_obj) - - return all_configs + def _do_skips(cls): all_configs = _possible_configs_for_cls(cls) reasons = [] @@ -427,19 +461,17 @@ def _do_skips(cls): for config_obj in list(all_configs): if exclusions.skip_if( exclusions.SpecPredicate(db_spec, op, spec) - ).predicate(config_obj): + ).predicate(config_obj): all_configs.remove(config_obj) - - if not all_configs: raise SkipTest( "'%s' unsupported on DB implementation %s%s" % ( cls.__name__, - ", ".join("'%s' = %s" % ( - config_obj.db.name, - config_obj.db.dialect.server_version_info) - for config_obj in config.Config.all_configs() - ), + ", ".join("'%s' = %s" + % (config_obj.db.name, + config_obj.db.dialect.server_version_info) + for config_obj in config.Config.all_configs() + ), ", ".join(reasons) ) ) @@ -455,6 +487,6 @@ def _do_skips(cls): if config._current not in all_configs: _setup_config(all_configs.pop(), cls) + def _setup_config(config_obj, ctx): config._current.push(config_obj, testing) - diff --git a/lib/sqlalchemy/testing/plugin/pytestplugin.py b/lib/sqlalchemy/testing/plugin/pytestplugin.py index 74d5cc083..11238bbac 100644 --- a/lib/sqlalchemy/testing/plugin/pytestplugin.py +++ b/lib/sqlalchemy/testing/plugin/pytestplugin.py @@ -4,6 +4,7 @@ import inspect from . import plugin_base import collections + def pytest_addoption(parser): group = parser.getgroup("sqlalchemy") @@ -11,7 +12,8 @@ def pytest_addoption(parser): callback_ = kw.pop("callback", None) if callback_: class CallableAction(argparse.Action): - def __call__(self, parser, namespace, values, option_string=None): + def __call__(self, parser, namespace, + values, option_string=None): callback_(option_string, values, parser) kw["action"] = CallableAction @@ -20,10 +22,12 @@ def pytest_addoption(parser): plugin_base.setup_options(make_option) plugin_base.read_config() + def pytest_configure(config): plugin_base.pre_begin(config.option) - plugin_base.set_coverage_flag(bool(getattr(config.option, "cov_source", False))) + plugin_base.set_coverage_flag(bool(getattr(config.option, + "cov_source", False))) plugin_base.post_begin() @@ -42,12 +46,14 @@ def pytest_collection_modifyitems(session, config, items): rebuilt_items = collections.defaultdict(list) test_classes = set(item.parent for item in items) for test_class in test_classes: - for sub_cls in plugin_base.generate_sub_tests(test_class.cls, test_class.parent.module): + for sub_cls in plugin_base.generate_sub_tests( + test_class.cls, test_class.parent.module): if sub_cls is not test_class.cls: list_ = rebuilt_items[test_class.cls] - for inst in pytest.Class(sub_cls.__name__, - parent=test_class.parent.parent).collect(): + for inst in pytest.Class( + sub_cls.__name__, + parent=test_class.parent.parent).collect(): list_.extend(inst.collect()) newitems = [] @@ -61,12 +67,10 @@ def pytest_collection_modifyitems(session, config, items): # seems like the functions attached to a test class aren't sorted already? # is that true and why's that? (when using unittest, they're sorted) items[:] = sorted(newitems, key=lambda item: ( - item.parent.parent.parent.name, - item.parent.parent.name, - item.name - ) - ) - + item.parent.parent.parent.name, + item.parent.parent.name, + item.name + )) def pytest_pycollect_makeitem(collector, name, obj): @@ -82,6 +86,7 @@ def pytest_pycollect_makeitem(collector, name, obj): _current_class = None + def pytest_runtest_setup(item): # here we seem to get called only based on what we collected # in pytest_collection_modifyitems. So to do class-based stuff @@ -100,10 +105,12 @@ def pytest_runtest_setup(item): # this is needed for the class-level, to ensure that the # teardown runs after the class is completed with its own # class-level teardown... - item.parent.parent.addfinalizer(lambda: class_teardown(item.parent.parent)) + item.parent.parent.addfinalizer( + lambda: class_teardown(item.parent.parent)) test_setup(item) + def pytest_runtest_teardown(item): # ...but this works better as the hook here rather than # using a finalizer, as the finalizer seems to get in the way @@ -111,15 +118,19 @@ def pytest_runtest_teardown(item): # py.test assertion stuff instead) test_teardown(item) + def test_setup(item): - plugin_base.before_test(item, - item.parent.module.__name__, item.parent.cls, item.name) + plugin_base.before_test(item, item.parent.module.__name__, + item.parent.cls, item.name) + def test_teardown(item): plugin_base.after_test(item) + def class_setup(item): plugin_base.start_test_class(item.cls) + def class_teardown(item): plugin_base.stop_test_class(item.cls) |
