1
0
mirror of https://github.com/django/django.git synced 2025-10-24 06:06:09 +00:00

Fixed #12991 -- Added unittest2 support. Thanks to PaulM for the draft patch, and to Luke, Karen, Justin, Alex, Łukasz Rekucki, and Chuck Harmston for their help testing and reviewing the final patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14139 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee
2010-10-11 12:55:17 +00:00
parent 1070c57b83
commit 121d2e3678
106 changed files with 3841 additions and 1020 deletions

View File

@@ -3,5 +3,5 @@ Django Unit Test and Doctest framework.
"""
from django.test.client import Client
from django.test.testcases import TestCase, TransactionTestCase
from django.test.testcases import TestCase, TransactionTestCase, skipIfDBFeature, skipUnlessDBFeature
from django.test.utils import Approximate

View File

@@ -1,12 +1,12 @@
import sys
import signal
import unittest
from django.conf import settings
from django.db.models import get_app, get_apps
from django.test import _doctest as doctest
from django.test.utils import setup_test_environment, teardown_test_environment
from django.test.testcases import OutputChecker, DocTestRunner, TestCase
from django.utils import unittest
# The module name for tests outside models.py
TEST_MODULE = 'tests'
@@ -14,52 +14,13 @@ TEST_MODULE = 'tests'
doctestOutputChecker = OutputChecker()
class DjangoTestRunner(unittest.TextTestRunner):
def __init__(self, verbosity=0, failfast=False, **kwargs):
super(DjangoTestRunner, self).__init__(verbosity=verbosity, **kwargs)
self.failfast = failfast
self._keyboard_interrupt_intercepted = False
def run(self, *args, **kwargs):
"""
Runs the test suite after registering a custom signal handler
that triggers a graceful exit when Ctrl-C is pressed.
"""
self._default_keyboard_interrupt_handler = signal.signal(signal.SIGINT,
self._keyboard_interrupt_handler)
try:
result = super(DjangoTestRunner, self).run(*args, **kwargs)
finally:
signal.signal(signal.SIGINT, self._default_keyboard_interrupt_handler)
return result
def _keyboard_interrupt_handler(self, signal_number, stack_frame):
"""
Handles Ctrl-C by setting a flag that will stop the test run when
the currently running test completes.
"""
self._keyboard_interrupt_intercepted = True
sys.stderr.write(" <Test run halted by Ctrl-C> ")
# Set the interrupt handler back to the default handler, so that
# another Ctrl-C press will trigger immediate exit.
signal.signal(signal.SIGINT, self._default_keyboard_interrupt_handler)
def _makeResult(self):
result = super(DjangoTestRunner, self)._makeResult()
failfast = self.failfast
def stoptest_override(func):
def stoptest(test):
# If we were set to failfast and the unit test failed,
# or if the user has typed Ctrl-C, report and quit
if (failfast and not result.wasSuccessful()) or \
self._keyboard_interrupt_intercepted:
result.stop()
func(test)
return stoptest
result.stopTest = stoptest_override(result.stopTest)
return result
def __init__(self, *args, **kwargs):
import warnings
warnings.warn(
"DjangoTestRunner is deprecated; it's functionality is indistinguishable from TextTestRunner",
PendingDeprecationWarning
)
super(DjangoTestRunner, self).__init__(*args, **kwargs)
def get_tests(app_module):
try:
@@ -232,6 +193,7 @@ class DjangoTestSuiteRunner(object):
def setup_test_environment(self, **kwargs):
setup_test_environment()
settings.DEBUG = False
unittest.installHandler()
def build_suite(self, test_labels, extra_tests=None, **kwargs):
suite = unittest.TestSuite()
@@ -271,7 +233,7 @@ class DjangoTestSuiteRunner(object):
return old_names, mirrors
def run_suite(self, suite, **kwargs):
return DjangoTestRunner(verbosity=self.verbosity, failfast=self.failfast).run(suite)
return unittest.TextTestRunner(verbosity=self.verbosity, failfast=self.failfast).run(suite)
def teardown_databases(self, old_config, **kwargs):
from django.db import connections
@@ -284,6 +246,7 @@ class DjangoTestSuiteRunner(object):
connection.creation.destroy_test_db(old_name, self.verbosity)
def teardown_test_environment(self, **kwargs):
unittest.removeHandler()
teardown_test_environment()
def suite_result(self, suite, result, **kwargs):

View File

@@ -1,5 +1,4 @@
import re
import unittest
from urlparse import urlsplit, urlunsplit
from xml.dom.minidom import parseString, Node
@@ -7,12 +6,14 @@ from django.conf import settings
from django.core import mail
from django.core.management import call_command
from django.core.urlresolvers import clear_url_caches
from django.db import transaction, connections, DEFAULT_DB_ALIAS
from django.db import transaction, connection, connections, DEFAULT_DB_ALIAS
from django.http import QueryDict
from django.test import _doctest as doctest
from django.test.client import Client
from django.utils import simplejson
from django.utils import simplejson, unittest
from django.utils.encoding import smart_str
from django.utils.functional import wraps
try:
all
@@ -22,6 +23,7 @@ except NameError:
normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s)
normalize_decimals = lambda s: re.sub(r"Decimal\('(\d+(\.\d*)?)'\)", lambda m: "Decimal(\"%s\")" % m.groups()[0], s)
def to_list(value):
"""
Puts value into a list if it's not already one.
@@ -472,7 +474,7 @@ def connections_support_transactions():
Returns True if all connections support transactions. This is messy
because 2.4 doesn't support any or all.
"""
return all(conn.settings_dict['SUPPORTS_TRANSACTIONS']
return all(conn.features.supports_transactions
for conn in connections.all())
class TestCase(TransactionTestCase):
@@ -528,3 +530,25 @@ class TestCase(TransactionTestCase):
for connection in connections.all():
connection.close()
def _deferredSkip(condition, reason):
def decorator(test_item):
if not (isinstance(test_item, type) and issubclass(test_item, TestCase)):
@wraps(test_item)
def skip_wrapper(*args, **kwargs):
if condition():
raise unittest.SkipTest(reason)
test_item = skip_wrapper
test_item.__unittest_skip_why__ = reason
return test_item
return decorator
def skipIfDBFeature(feature):
"Skip a test if a database has the named feature"
return _deferredSkip(lambda: getattr(connection.features, feature),
"Database has feature %s" % feature)
def skipUnlessDBFeature(feature):
"Skip a test unless a database has the named feature"
return _deferredSkip(lambda: not getattr(connection.features, feature),
"Database doesn't support feature %s" % feature)