diff options
| author | Russell Keith-Magee <russell@keith-magee.com> | 2008-06-30 12:34:29 +0000 |
|---|---|---|
| committer | Russell Keith-Magee <russell@keith-magee.com> | 2008-06-30 12:34:29 +0000 |
| commit | 415bd694f9de8252e8d47bdf3df73cc62ca97728 (patch) | |
| tree | 237fa918225a9cdda54bff352819bb89650dff73 | |
| parent | 61898d86276d236388c66a8f629ff6c3cfe04800 (diff) | |
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
| -rw-r--r-- | django/contrib/formtools/tests.py | 6 | ||||
| -rw-r--r-- | django/core/urlresolvers.py | 5 | ||||
| -rw-r--r-- | django/test/testcases.py | 25 | ||||
| -rw-r--r-- | docs/testing.txt | 31 | ||||
| -rw-r--r-- | tests/regressiontests/test_client_regress/models.py | 19 |
5 files changed, 81 insertions, 5 deletions
diff --git a/django/contrib/formtools/tests.py b/django/contrib/formtools/tests.py index 143857ad58..ba241e9dc6 100644 --- a/django/contrib/formtools/tests.py +++ b/django/contrib/formtools/tests.py @@ -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. diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py index 2ad63bfc7d..ff0bcbcfea 100644 --- a/django/core/urlresolvers.py +++ b/django/core/urlresolvers.py @@ -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() diff --git a/django/test/testcases.py b/django/test/testcases.py index ee83b960a6..3bad3995bb 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -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): diff --git a/docs/testing.txt b/docs/testing.txt index befa6979af..0b18545efb 100644 --- a/docs/testing.txt +++ b/docs/testing.txt @@ -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 ~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/regressiontests/test_client_regress/models.py b/tests/regressiontests/test_client_regress/models.py index a204ec3e72..37e81668b6 100644 --- a/tests/regressiontests/test_client_regress/models.py +++ b/tests/regressiontests/test_client_regress/models.py @@ -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/') |
