summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2022-11-26 11:03:45 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2022-11-26 17:24:04 -0500
commit5cc3825da3cdda6bd80e4fe7250b795c15ca4be3 (patch)
tree16036a4cf11ca3fe3d28dbac39b87824befd534e /lib/sqlalchemy
parent25c2b7dd105a6622eff2c7631d3c2d6eb978dc1f (diff)
downloadsqlalchemy-5cc3825da3cdda6bd80e4fe7250b795c15ca4be3.tar.gz
add new variation helper
I'm using a lot of @testing.combinations with either a boolean True/False, or a series of string names, each indicating some case to switch on. I want a descriptive name in the test run (not True/False) and I don't want to compare strings. So make a new helper around @combinations that provides an object interface that has booleans inside of it, prints nicely in the test output, raises an error if you name the case incorrectly. Before: test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[False-False-both] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[False-False-key] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[False-False-name] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[False-True-both] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[False-True-key] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[False-True-name] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[True-False-both] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[True-False-key] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[True-False-name] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[True-True-both] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[True-True-key] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[True-True-name] PASSED After: test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[not_use_add_property-deferred-both] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[not_use_add_property-deferred-key] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[not_use_add_property-deferred-name] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[not_use_add_property-not_deferred-both] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[not_use_add_property-not_deferred-key] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[not_use_add_property-not_deferred-name] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[use_add_property-deferred-both] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[use_add_property-deferred-key] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[use_add_property-deferred-name] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[use_add_property-not_deferred-both] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[use_add_property-not_deferred-key] PASSED test/orm/declarative/test_typed_mapping.py::MappedColumnTest::test_separate_name[use_add_property-not_deferred-name] PASSED Change-Id: Idde87632581ee69e0f47360966758583dfd8baab
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/testing/__init__.py1
-rw-r--r--lib/sqlalchemy/testing/config.py75
2 files changed, 76 insertions, 0 deletions
diff --git a/lib/sqlalchemy/testing/__init__.py b/lib/sqlalchemy/testing/__init__.py
index 76445a444..3a028f002 100644
--- a/lib/sqlalchemy/testing/__init__.py
+++ b/lib/sqlalchemy/testing/__init__.py
@@ -54,6 +54,7 @@ from .config import db
from .config import fixture
from .config import requirements as requires
from .config import skip_test
+from .config import variation
from .exclusions import _is_excluded
from .exclusions import _server_version
from .exclusions import against as _against
diff --git a/lib/sqlalchemy/testing/config.py b/lib/sqlalchemy/testing/config.py
index 44133984b..749d04248 100644
--- a/lib/sqlalchemy/testing/config.py
+++ b/lib/sqlalchemy/testing/config.py
@@ -128,6 +128,81 @@ def combinations_list(
return combinations(*arg_iterable, **kw)
+class _variation_base:
+ __slots__ = ("name", "argname")
+
+ def __init__(self, case, argname, case_names):
+ self.name = case
+ self.argname = argname
+ for casename in case_names:
+ setattr(self, casename, casename == case)
+
+ def __bool__(self):
+ return self.name == self.argname
+
+ def __nonzero__(self):
+ return not self.__bool__()
+
+
+def variation(argname, cases):
+ """a helper around testing.combinations that provides a single namespace
+ that can be used as a switch.
+
+ e.g.::
+
+ @testing.variation("querytyp", ["select", "subquery", "legacy_query"])
+ @testing.variation("lazy", ["select", "raise", "raise_on_sql"])
+ def test_thing(
+ self,
+ querytyp,
+ lazy,
+ decl_base
+ ):
+ class Thing(decl_base):
+ __tablename__ = 'thing'
+
+ # use name directly
+ rel = relationship("Rel", lazy=lazy.name)
+
+ # use as a switch
+ if querytyp.select:
+ stmt = select(Thing)
+ elif querytyp.subquery:
+ stmt = select(Thing).subquery()
+ elif querytyp.legacy_query:
+ stmt = Session.query(Thing)
+ else:
+ assert False
+
+
+ The variable provided is a slots object of boolean variables, as well
+ as the name of the case itself under the attribute ".name"
+
+ """
+
+ case_names = [
+ argname if c is True else "not_" + argname if c is False else c
+ for c in cases
+ ]
+
+ typ = type(
+ argname,
+ (_variation_base,),
+ {
+ "__slots__": tuple(case_names),
+ },
+ )
+
+ return combinations(
+ *[
+ (casename, typ(casename, argname, case_names))
+ for casename in case_names
+ ],
+ id_="ia",
+ argnames=argname,
+ )
+
+
def fixture(*arg: Any, **kw: Any) -> Any:
return _fixture_functions.fixture(*arg, **kw)