diff --git a/django/test/testcases.py b/django/test/testcases.py index d0442360ac..6f3f1c00e4 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -879,10 +879,19 @@ class TestCase(TransactionTestCase): 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 decorator(test_func): if not (isinstance(test_func, type) and - issubclass(test_func, TestCase)): + issubclass(test_func, unittest.TestCase)): @wraps(test_func) def skip_wrapper(*args, **kwargs): if condition(): @@ -890,7 +899,9 @@ def _deferredSkip(condition, reason): return test_func(*args, **kwargs) test_item = skip_wrapper else: + # Assume a class is decorated test_item = test_func + test_item.__unittest_skip__ = CheckCondition(condition) test_item.__unittest_skip_why__ = reason return test_item return decorator diff --git a/docs/topics/testing/overview.txt b/docs/topics/testing/overview.txt index 73f2daa294..0380d6931b 100644 --- a/docs/topics/testing/overview.txt +++ b/docs/topics/testing/overview.txt @@ -1804,7 +1804,8 @@ for skipping tests. .. 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 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): # ... conditional test code +.. versionchanged:: 1.7 + + ``skipIfDBFeature`` can now be used to decorate a ``TestCase`` class. + .. 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. For example, the following test will only be executed if the database @@ -1828,3 +1833,7 @@ under MySQL with MyISAM tables):: @skipUnlessDBFeature('supports_transactions') def test_transaction_behavior(self): # ... conditional test code + +.. versionchanged:: 1.7 + + ``skipUnlessDBFeature`` can now be used to decorate a ``TestCase`` class. diff --git a/tests/test_utils/tests.py b/tests/test_utils/tests.py index 2c2bc24d72..24aa433dd3 100644 --- a/tests/test_utils/tests.py +++ b/tests/test_utils/tests.py @@ -2,13 +2,12 @@ from __future__ import absolute_import, unicode_literals import unittest -from unittest import skip from django.db import connection from django.forms import EmailField, IntegerField from django.http import HttpResponse 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.utils import CaptureQueriesContext, IgnoreAllDeprecationWarningsMixin from django.utils import six @@ -27,6 +26,29 @@ class SkippingTestCase(TestCase): 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): urls = 'test_utils.urls' @@ -561,7 +583,7 @@ class SkippingExtraTests(TestCase): with self.assertNumQueries(0): 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): pass