summaryrefslogtreecommitdiff
path: root/django/test/testcases.py
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2019-01-12 16:14:54 -0500
committerTim Graham <timograham@gmail.com>2019-01-14 16:16:30 -0500
commitb181aba7dd24c73ec9923c39e35393b0487a5f47 (patch)
treee5d82ea665a4b6eace3e07fb53d78808b936c624 /django/test/testcases.py
parentf5b635086a07c9df5897e69685ebdc3a04049ec6 (diff)
Refs #28478 -- Prevented database feature based skipping on tests disallowing queries.
Database features may require a connection to be established to determine whether or not they are enabled.
Diffstat (limited to 'django/test/testcases.py')
-rw-r--r--django/test/testcases.py33
1 files changed, 29 insertions, 4 deletions
diff --git a/django/test/testcases.py b/django/test/testcases.py
index 0e1da33064..3dd14a08c0 100644
--- a/django/test/testcases.py
+++ b/django/test/testcases.py
@@ -1205,12 +1205,24 @@ class CheckCondition:
return False
-def _deferredSkip(condition, reason):
+def _deferredSkip(condition, reason, name):
def decorator(test_func):
+ nonlocal condition
if not (isinstance(test_func, type) and
issubclass(test_func, unittest.TestCase)):
@wraps(test_func)
def skip_wrapper(*args, **kwargs):
+ if (args and isinstance(args[0], unittest.TestCase) and
+ connection.alias not in getattr(args[0], 'databases', {})):
+ raise ValueError(
+ "%s cannot be used on %s as %s doesn't allow queries "
+ "against the %r database." % (
+ name,
+ args[0],
+ args[0].__class__.__qualname__,
+ connection.alias,
+ )
+ )
if condition():
raise unittest.SkipTest(reason)
return test_func(*args, **kwargs)
@@ -1218,6 +1230,16 @@ def _deferredSkip(condition, reason):
else:
# Assume a class is decorated
test_item = test_func
+ databases = getattr(test_item, 'databases', None)
+ if not databases or connection.alias not in databases:
+ # Defer raising to allow importing test class's module.
+ def condition():
+ raise ValueError(
+ "%s cannot be used on %s as it doesn't allow queries "
+ "against the '%s' database." % (
+ name, test_item, connection.alias,
+ )
+ )
# Retrieve the possibly existing value from the class's dict to
# avoid triggering the descriptor.
skip = test_func.__dict__.get('__unittest_skip__')
@@ -1233,7 +1255,8 @@ def skipIfDBFeature(*features):
"""Skip a test if a database has at least one of the named features."""
return _deferredSkip(
lambda: any(getattr(connection.features, feature, False) for feature in features),
- "Database has feature(s) %s" % ", ".join(features)
+ "Database has feature(s) %s" % ", ".join(features),
+ 'skipIfDBFeature',
)
@@ -1241,7 +1264,8 @@ def skipUnlessDBFeature(*features):
"""Skip a test unless a database has all the named features."""
return _deferredSkip(
lambda: not all(getattr(connection.features, feature, False) for feature in features),
- "Database doesn't support feature(s): %s" % ", ".join(features)
+ "Database doesn't support feature(s): %s" % ", ".join(features),
+ 'skipUnlessDBFeature',
)
@@ -1249,7 +1273,8 @@ def skipUnlessAnyDBFeature(*features):
"""Skip a test unless a database has any of the named features."""
return _deferredSkip(
lambda: not any(getattr(connection.features, feature, False) for feature in features),
- "Database doesn't support any of the feature(s): %s" % ", ".join(features)
+ "Database doesn't support any of the feature(s): %s" % ", ".join(features),
+ 'skipUnlessAnyDBFeature',
)