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

Thanks Tim Graham for the review and improved patch.
This commit is contained in:
Claude Paroz 2013-07-19 20:30:14 +02:00
parent a269ea4fe0
commit 6d52844b9b
3 changed files with 48 additions and 6 deletions

View File

@ -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):
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

View File

@ -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)::
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)::
@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.

View File

@ -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):
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):
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