summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2014-03-02 20:34:21 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2014-03-02 20:34:21 -0500
commit746789942521a3cc0bd9b80ceda08c9a414802ca (patch)
treecf8d29b80cec417430dc21a45374c43e8c76c715 /lib
parenteb7a788364c22dc5925c0e28eb7a966bd646db3f (diff)
downloadsqlalchemy-746789942521a3cc0bd9b80ceda08c9a414802ca.tar.gz
- working through this..
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/testing/fixtures.py10
-rw-r--r--lib/sqlalchemy/testing/plugin/noseplugin.py9
-rw-r--r--lib/sqlalchemy/testing/plugin/plugin_base.py17
-rw-r--r--lib/sqlalchemy/testing/plugin/pytestplugin.py69
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)