Commit 415bd694 authored by Russell Keith-Magee's avatar Russell Keith-Magee
Browse files

Fixed #7521 -- Added the ability to customize ROOT_URLCONF for the duration of...

Fixed #7521 -- Added the ability to customize ROOT_URLCONF for the duration of a TestCase. Thanks to Mark Fargas (telenieko) for his work on this patch.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@7805 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 61898d86
Loading
Loading
Loading
Loading
+1 −5
Original line number Diff line number Diff line
@@ -21,18 +21,14 @@ class TestForm(forms.Form):


class PreviewTests(TestCase):
    urls = 'django.contrib.formtools.test_urls'

    def setUp(self):
        self._old_root_urlconf = settings.ROOT_URLCONF
        settings.ROOT_URLCONF = 'django.contrib.formtools.test_urls'
        # Create a FormPreview instance to share between tests
        self.preview = preview.FormPreview(TestForm)
        input_template = '<input type="hidden" name="%s" value="%s" />'
        self.input = input_template % (self.preview.unused_name('stage'), "%d")

    def tearDown(self):
        settings.ROOT_URLCONF = self._old_root_urlconf
        
    def test_unused_name(self):
        """
        Verifies name mangling to get uniue field name.
+5 −0
Original line number Diff line number Diff line
@@ -296,3 +296,8 @@ def reverse(viewname, urlconf=None, args=None, kwargs=None):
    kwargs = kwargs or {}
    return iri_to_uri(u'/' + get_resolver(urlconf).reverse(viewname, *args, **kwargs))

def clear_url_caches():
    global _resolver_cache
    global _callable_cache
    _resolver_cache.clear()
    _callable_cache.clear()
+25 −0
Original line number Diff line number Diff line
@@ -4,10 +4,12 @@ from urlparse import urlsplit, urlunsplit

from django.http import QueryDict
from django.db import transaction
from django.conf import settings
from django.core import mail
from django.core.management import call_command
from django.test import _doctest as doctest
from django.test.client import Client
from django.core.urlresolvers import clear_url_caches

normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s)

@@ -54,6 +56,8 @@ class TestCase(unittest.TestCase):
            * Flushing the database.
            * If the Test Case class has a 'fixtures' member, installing the 
              named fixtures.
            * If the Test Case class has a 'urls' member, replace the
              ROOT_URLCONF with it.
            * Clearing the mail test outbox.
        """
        call_command('flush', verbosity=0, interactive=False)
@@ -61,6 +65,10 @@ class TestCase(unittest.TestCase):
            # We have to use this slightly awkward syntax due to the fact
            # that we're using *args and **kwargs together.
            call_command('loaddata', *self.fixtures, **{'verbosity': 0})
        if hasattr(self, 'urls'):
            self._old_root_urlconf = settings.ROOT_URLCONF
            settings.ROOT_URLCONF = self.urls
            clear_url_caches()
        mail.outbox = []

    def __call__(self, result=None):
@@ -79,6 +87,23 @@ class TestCase(unittest.TestCase):
            result.addError(self, sys.exc_info())
            return
        super(TestCase, self).__call__(result)
        try:
            self._post_teardown()
        except (KeyboardInterrupt, SystemExit):
            raise
        except Exception:
            import sys
            result.addError(self, sys.exc_info())
            return

    def _post_teardown(self):
        """ Performs any post-test things. This includes:

            * Putting back the original ROOT_URLCONF if it was changed.
        """
        if hasattr(self, '_old_root_urlconf'):
            settings.ROOT_URLCONF = self._old_root_urlconf
            clear_url_caches()

    def assertRedirects(self, response, expected_url, status_code=302,
                        target_status_code=200, host=None):
+31 −0
Original line number Diff line number Diff line
@@ -797,6 +797,37 @@ another test, or by the order of test execution.
.. _dumpdata documentation: ../django-admin/#dumpdata-appname-appname
.. _loaddata documentation: ../django-admin/#loaddata-fixture-fixture

URLconf configuration
~~~~~~~~~~~~~~~~~~~~~

**New in Django development version**

If your application provides views, you may want to include tests that
use the test client to exercise those views. However, an end user is free
to deploy the views in your application at any URL of their choosing.
This means that your tests can't rely upon the fact that your views will
be available at a particular URL.

In order to provide a reliable URL space for your test,
``django.test.TestCase`` provides the ability to customize the URLconf
configuration for the duration of the execution of a test suite.
If your ``TestCase`` instance defines an ``urls`` attribute, the
``TestCase`` will use the value of that attribute as the ``ROOT_URLCONF``
for the duration of that test. 

For example::

    from django.test import TestCase
    
    class TestMyViews(TestCase):
        urls = 'myapp.test_urls'

        def testIndexPageView(self):
            # Here you'd test your view using ``Client``.

This test case will use the contents of ``myapp.test_urls`` as the
URLconf for the duration of the test case.

Emptying the test outbox
~~~~~~~~~~~~~~~~~~~~~~~~

+19 −0
Original line number Diff line number Diff line
@@ -318,3 +318,22 @@ class ExceptionTests(TestCase):
            self.client.get("/test_client_regress/staff_only/")
        except SuspiciousOperation:
            self.fail("Staff should be able to visit this page")

# We need two different tests to check URLconf subsitution -  one to check
# it was changed, and another one (without self.urls) to check it was reverted on
# teardown. This pair of tests relies upon the alphabetical ordering of test execution.
class UrlconfSubstitutionTests(TestCase):
    urls = 'regressiontests.test_client_regress.urls'

    def test_urlconf_was_changed(self):
        "TestCase can enforce a custom URLConf on a per-test basis"
        url = reverse('arg_view', args=['somename'])
        self.assertEquals(url, '/arg_view/somename/')

# This test needs to run *after* UrlconfSubstitutionTests; the zz prefix in the
# name is to ensure alphabetical ordering.
class zzUrlconfSubstitutionTests(TestCase):
    def test_urlconf_was_reverted(self):
        "URLconf is reverted to original value after modification in a TestCase"
        url = reverse('arg_view', args=['somename'])
        self.assertEquals(url, '/test_client_regress/arg_view/somename/')