Kaydet (Commit) 6d52844b authored tarafından Claude Paroz's avatar Claude Paroz

Fixed #18551 -- Enabled skipIfDBFeature/skipUnlessDBFeature to decorate a class

Thanks Tim Graham for the review and improved patch.
üst a269ea4f
...@@ -879,10 +879,19 @@ class TestCase(TransactionTestCase): ...@@ -879,10 +879,19 @@ class TestCase(TransactionTestCase):
self.atomics[db_name].__exit__(None, None, None) self.atomics[db_name].__exit__(None, None, None)
class CheckCondition(object):
"""Descriptor class for deferred condition checking"""
def __init__(self, cond_func):
self.cond_func = cond_func
def __get__(self, obj, objtype):
return self.cond_func()
def _deferredSkip(condition, reason): def _deferredSkip(condition, reason):
def decorator(test_func): def decorator(test_func):
if not (isinstance(test_func, type) and if not (isinstance(test_func, type) and
issubclass(test_func, TestCase)): issubclass(test_func, unittest.TestCase)):
@wraps(test_func) @wraps(test_func)
def skip_wrapper(*args, **kwargs): def skip_wrapper(*args, **kwargs):
if condition(): if condition():
...@@ -890,7 +899,9 @@ def _deferredSkip(condition, reason): ...@@ -890,7 +899,9 @@ def _deferredSkip(condition, reason):
return test_func(*args, **kwargs) return test_func(*args, **kwargs)
test_item = skip_wrapper test_item = skip_wrapper
else: else:
# Assume a class is decorated
test_item = test_func test_item = test_func
test_item.__unittest_skip__ = CheckCondition(condition)
test_item.__unittest_skip_why__ = reason test_item.__unittest_skip_why__ = reason
return test_item return test_item
return decorator return decorator
......
...@@ -1804,7 +1804,8 @@ for skipping tests. ...@@ -1804,7 +1804,8 @@ for skipping tests.
.. function:: skipIfDBFeature(feature_name_string) .. function:: skipIfDBFeature(feature_name_string)
Skip the decorated test if the named database feature is supported. Skip the decorated test or ``TestCase`` if the named database feature is
supported.
For example, the following test will not be executed if the database For example, the following test will not be executed if the database
supports transactions (e.g., it would *not* run under PostgreSQL, but supports transactions (e.g., it would *not* run under PostgreSQL, but
...@@ -1815,9 +1816,13 @@ it would under MySQL with MyISAM tables):: ...@@ -1815,9 +1816,13 @@ it would under MySQL with MyISAM tables)::
def test_transaction_behavior(self): def test_transaction_behavior(self):
# ... conditional test code # ... conditional test code
.. versionchanged:: 1.7
``skipIfDBFeature`` can now be used to decorate a ``TestCase`` class.
.. function:: skipUnlessDBFeature(feature_name_string) .. function:: skipUnlessDBFeature(feature_name_string)
Skip the decorated test if the named database feature is *not* Skip the decorated test or ``TestCase`` if the named database feature is *not*
supported. supported.
For example, the following test will only be executed if the database For example, the following test will only be executed if the database
...@@ -1828,3 +1833,7 @@ under MySQL with MyISAM tables):: ...@@ -1828,3 +1833,7 @@ under MySQL with MyISAM tables)::
@skipUnlessDBFeature('supports_transactions') @skipUnlessDBFeature('supports_transactions')
def test_transaction_behavior(self): def test_transaction_behavior(self):
# ... conditional test code # ... conditional test code
.. versionchanged:: 1.7
``skipUnlessDBFeature`` can now be used to decorate a ``TestCase`` class.
...@@ -2,13 +2,12 @@ ...@@ -2,13 +2,12 @@
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
import unittest import unittest
from unittest import skip
from django.db import connection from django.db import connection
from django.forms import EmailField, IntegerField from django.forms import EmailField, IntegerField
from django.http import HttpResponse from django.http import HttpResponse
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature from django.test import SimpleTestCase, TestCase, skipIfDBFeature, skipUnlessDBFeature
from django.test.html import HTMLParseError, parse_html from django.test.html import HTMLParseError, parse_html
from django.test.utils import CaptureQueriesContext, IgnoreAllDeprecationWarningsMixin from django.test.utils import CaptureQueriesContext, IgnoreAllDeprecationWarningsMixin
from django.utils import six from django.utils import six
...@@ -27,6 +26,29 @@ class SkippingTestCase(TestCase): ...@@ -27,6 +26,29 @@ class SkippingTestCase(TestCase):
self.assertRaises(ValueError, test_func) self.assertRaises(ValueError, test_func)
class SkippingClassTestCase(TestCase):
def test_skip_class_unless_db_feature(self):
@skipUnlessDBFeature("__class__")
class NotSkippedTests(unittest.TestCase):
def test_dummy(self):
return
@skipIfDBFeature("__class__")
class SkippedTests(unittest.TestCase):
def test_will_be_skipped(self):
self.fail("We should never arrive here.")
test_suite = unittest.TestSuite()
test_suite.addTest(NotSkippedTests('test_dummy'))
try:
test_suite.addTest(SkippedTests('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)
class AssertNumQueriesTests(TestCase): class AssertNumQueriesTests(TestCase):
urls = 'test_utils.urls' urls = 'test_utils.urls'
...@@ -561,7 +583,7 @@ class SkippingExtraTests(TestCase): ...@@ -561,7 +583,7 @@ class SkippingExtraTests(TestCase):
with self.assertNumQueries(0): with self.assertNumQueries(0):
super(SkippingExtraTests, self).__call__(result) super(SkippingExtraTests, self).__call__(result)
@skip("Fixture loading should not be performed for skipped tests.") @unittest.skip("Fixture loading should not be performed for skipped tests.")
def test_fixtures_are_skipped(self): def test_fixtures_are_skipped(self):
pass pass
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment