summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2016-09-12 22:06:31 -0400
committerSimon Charette <charette.s@gmail.com>2016-09-13 14:12:20 -0400
commit18c72d59e0807dae75ac2c34890d08c1e0972d0a (patch)
tree0f7059ab521c1e12402a0c9a3316290e9c4d6f19
parent0627858ada32e13bafef74f9541dafd8c854ae25 (diff)
Fixed #27214 -- Made skip db features decorators respect wrapping order and inheritance.
-rw-r--r--django/test/testcases.py27
-rw-r--r--tests/test_utils/tests.py12
2 files changed, 32 insertions, 7 deletions
diff --git a/django/test/testcases.py b/django/test/testcases.py
index 8fd84b1423..be5720a80b 100644
--- a/django/test/testcases.py
+++ b/django/test/testcases.py
@@ -1083,11 +1083,23 @@ class TestCase(TransactionTestCase):
class CheckCondition(object):
"""Descriptor class for deferred condition checking"""
- def __init__(self, cond_func):
- self.cond_func = cond_func
+ def __init__(self, *conditions):
+ self.conditions = conditions
+
+ def add_condition(self, condition, reason):
+ return self.__class__(*self.conditions + ((condition, reason),))
def __get__(self, instance, cls=None):
- return self.cond_func()
+ # Trigger access for all bases.
+ if any(getattr(base, '__unittest_skip__', False) for base in cls.__bases__):
+ return True
+ for condition, reason in self.conditions:
+ if condition():
+ # Override this descriptor's value and set the skip reason.
+ cls.__unittest_skip__ = True
+ cls.__unittest_skip_why__ = reason
+ return True
+ return False
def _deferredSkip(condition, reason):
@@ -1103,8 +1115,13 @@ def _deferredSkip(condition, reason):
else:
# Assume a class is decorated
test_item = test_func
- test_item.__unittest_skip__ = CheckCondition(condition)
- test_item.__unittest_skip_why__ = reason
+ # Retrieve the possibly existing value from the class's dict to
+ # avoid triggering the descriptor.
+ skip = test_func.__dict__.get('__unittest_skip__')
+ if isinstance(skip, CheckCondition):
+ test_item.__unittest_skip__ = skip.add_condition(condition, reason)
+ elif skip is not True:
+ test_item.__unittest_skip__ = CheckCondition((condition, reason))
return test_item
return decorator
diff --git a/tests/test_utils/tests.py b/tests/test_utils/tests.py
index cd9b723a4e..1fb70e2aa3 100644
--- a/tests/test_utils/tests.py
+++ b/tests/test_utils/tests.py
@@ -106,20 +106,28 @@ class SkippingClassTestCase(SimpleTestCase):
def test_dummy(self):
return
+ @skipUnlessDBFeature("missing")
@skipIfDBFeature("__class__")
class SkippedTests(unittest.TestCase):
def test_will_be_skipped(self):
self.fail("We should never arrive here.")
+ @skipIfDBFeature("__dict__")
+ class SkippedTestsSubclass(SkippedTests):
+ pass
+
test_suite = unittest.TestSuite()
test_suite.addTest(NotSkippedTests('test_dummy'))
try:
test_suite.addTest(SkippedTests('test_will_be_skipped'))
+ test_suite.addTest(SkippedTestsSubclass('test_will_be_skipped'))
except unittest.SkipTest:
self.fail("SkipTest should not be raised at this stage")
result = unittest.TextTestRunner(stream=six.StringIO()).run(test_suite)
- self.assertEqual(result.testsRun, 2)
- self.assertEqual(len(result.skipped), 1)
+ self.assertEqual(result.testsRun, 3)
+ self.assertEqual(len(result.skipped), 2)
+ self.assertEqual(result.skipped[0][1], 'Database has feature(s) __class__')
+ self.assertEqual(result.skipped[1][1], 'Database has feature(s) __class__')
@override_settings(ROOT_URLCONF='test_utils.urls')