diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-03-02 20:34:21 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-03-02 20:34:21 -0500 |
| commit | 746789942521a3cc0bd9b80ceda08c9a414802ca (patch) | |
| tree | cf8d29b80cec417430dc21a45374c43e8c76c715 /lib | |
| parent | eb7a788364c22dc5925c0e28eb7a966bd646db3f (diff) | |
| download | sqlalchemy-746789942521a3cc0bd9b80ceda08c9a414802ca.tar.gz | |
- working through this..
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/sqlalchemy/testing/fixtures.py | 10 | ||||
| -rw-r--r-- | lib/sqlalchemy/testing/plugin/noseplugin.py | 9 | ||||
| -rw-r--r-- | lib/sqlalchemy/testing/plugin/plugin_base.py | 17 | ||||
| -rw-r--r-- | lib/sqlalchemy/testing/plugin/pytestplugin.py | 69 |
4 files changed, 93 insertions, 12 deletions
diff --git a/lib/sqlalchemy/testing/fixtures.py b/lib/sqlalchemy/testing/fixtures.py index 8717ce764..ffe21974f 100644 --- a/lib/sqlalchemy/testing/fixtures.py +++ b/lib/sqlalchemy/testing/fixtures.py @@ -14,8 +14,9 @@ import sys import sqlalchemy as sa from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta +import unittest -class TestBase(object): +class TestBase(unittest.TestCase): # A sequence of database names to always run, regardless of the # constraints below. __whitelist__ = () @@ -37,6 +38,13 @@ class TestBase(object): def assert_(self, val, msg=None): assert val, msg + def tearDown(self): + if hasattr(self, "teardown"): + self.teardown() + + def setUp(self): + if hasattr(self, "setup"): + self.setup() class TablesTest(TestBase): diff --git a/lib/sqlalchemy/testing/plugin/noseplugin.py b/lib/sqlalchemy/testing/plugin/noseplugin.py index f8fce4d48..b877ea7e4 100644 --- a/lib/sqlalchemy/testing/plugin/noseplugin.py +++ b/lib/sqlalchemy/testing/plugin/noseplugin.py @@ -16,16 +16,14 @@ import os from nose.plugins import Plugin from nose import SkipTest +# no package imports yet! this prevents us from tripping coverage +# too soon. import imp path = os.path.join(os.path.dirname(__file__), "plugin_base.py") plugin_base = imp.load_source("plugin_base", path) - class NoseSQLAlchemy(Plugin): - """ - Handles the setup and extra properties required for testing SQLAlchemy - """ enabled = True name = 'sqla_testing' @@ -82,9 +80,8 @@ class NoseSQLAlchemy(Plugin): else: return True - def beforeTest(self, test): - plugin_base.before_test(test) + plugin_base.before_test(test, test.id()) def afterTest(self, test): plugin_base.after_test(test) diff --git a/lib/sqlalchemy/testing/plugin/plugin_base.py b/lib/sqlalchemy/testing/plugin/plugin_base.py index 38fafa66b..961aba4d5 100644 --- a/lib/sqlalchemy/testing/plugin/plugin_base.py +++ b/lib/sqlalchemy/testing/plugin/plugin_base.py @@ -4,6 +4,13 @@ # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php +"""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. + +""" from __future__ import absolute_import @@ -306,16 +313,18 @@ def _setup_engine(cls): eng = engines.testing_engine(options=cls.__engine_options__) config._current.push_engine(eng, testing) -def before_test(test): +def before_test(test, id_): warnings.resetwarnings() - profiling._current_test = test.id() + profiling._current_test = id_ def after_test(test): engines.testing_reaper._after_test_ctx() warnings.resetwarnings() def _do_skips(cls): - + if cls is None: + import pdb + pdb.set_trace() all_configs = set(config.Config.all_configs()) reasons = [] @@ -347,7 +356,7 @@ def _do_skips(cls): if getattr(cls, '__skip_if__', False): for c in getattr(cls, '__skip_if__'): if c(): - raise SkipTest("'%s' skipped by %s" % ( + raise GenericSkip("'%s' skipped by %s" % ( cls.__name__, c.__name__) ) diff --git a/lib/sqlalchemy/testing/plugin/pytestplugin.py b/lib/sqlalchemy/testing/plugin/pytestplugin.py index 12b820865..8ad941f6b 100644 --- a/lib/sqlalchemy/testing/plugin/pytestplugin.py +++ b/lib/sqlalchemy/testing/plugin/pytestplugin.py @@ -2,8 +2,11 @@ import pytest import argparse import os +fixtures = None -# no package imports yet! dont want to trip coverage. + +# no package imports yet! this prevents us from tripping coverage +# too soon. import imp path = os.path.join(os.path.dirname(__file__), "plugin_base.py") plugin_base = imp.load_source("plugin_base", path) @@ -25,3 +28,67 @@ 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.post_begin() + global fixtures + from sqlalchemy.testing import fixtures + + +def pytest_collection_modifyitems(session, config, items): + items[:] = [ + item for item in items if + isinstance(item.cls, type) and issubclass(item.cls, fixtures.TestBase) + ] + +def pytest_pycollect_makeitem(collector, name, obj): + # TODO: this would be nicer? no clue what to + # return here + return None + +_current_class = None + +from pytest import Item +def pytest_runtest_setup(item): + # I'd like to get module/class/test level calls here + # but I don't quite see the pattern. + + # not really sure what determines if we're called + # here with pytest.Class, pytest.Module, does not seem to be + # consistent + + if not isinstance(item, Item): + return + global _current_class + + # ... so we're doing a little dance here to figure it out... + if item.parent is not _current_class: + class_setup(item.parent) + _current_class = item.parent + test_setup(item) + +def pytest_runtest_teardown(item, nextitem): + if not isinstance(item, Item): + return + + test_teardown(item) + + if nextitem is None or nextitem.parent is not _current_class: + class_teardown(item.parent) + +def test_setup(item): + id_ = "%s.%s:%s" % (item.parent.module.__name__, item.parent.name, item.name) + plugin_base.before_test(item, id_) + +def test_teardown(item): + plugin_base.after_test(item) + +def class_setup(item): + try: + plugin_base.start_test_class(item.cls) + except plugin_base.GenericSkip as gs: + pytest.skip(gs.message) + +def class_teardown(item): + # TODO: not working yet, this has to be called *after* test teardown/teardown_class + plugin_base.stop_test_class(item.cls) |
