mirror of
				https://github.com/django/django.git
				synced 2025-10-30 17:16:10 +00:00 
			
		
		
		
	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
This commit is contained in:
		| @@ -21,18 +21,14 @@ class TestForm(forms.Form): | |||||||
|  |  | ||||||
|  |  | ||||||
| class PreviewTests(TestCase): | class PreviewTests(TestCase): | ||||||
|  |     urls = 'django.contrib.formtools.test_urls' | ||||||
|  |  | ||||||
|     def setUp(self): |     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 |         # Create a FormPreview instance to share between tests | ||||||
|         self.preview = preview.FormPreview(TestForm) |         self.preview = preview.FormPreview(TestForm) | ||||||
|         input_template = '<input type="hidden" name="%s" value="%s" />' |         input_template = '<input type="hidden" name="%s" value="%s" />' | ||||||
|         self.input = input_template % (self.preview.unused_name('stage'), "%d") |         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): |     def test_unused_name(self): | ||||||
|         """ |         """ | ||||||
|         Verifies name mangling to get uniue field name. |         Verifies name mangling to get uniue field name. | ||||||
|   | |||||||
| @@ -296,3 +296,8 @@ def reverse(viewname, urlconf=None, args=None, kwargs=None): | |||||||
|     kwargs = kwargs or {} |     kwargs = kwargs or {} | ||||||
|     return iri_to_uri(u'/' + get_resolver(urlconf).reverse(viewname, *args, **kwargs)) |     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() | ||||||
|   | |||||||
| @@ -4,10 +4,12 @@ from urlparse import urlsplit, urlunsplit | |||||||
|  |  | ||||||
| from django.http import QueryDict | from django.http import QueryDict | ||||||
| from django.db import transaction | from django.db import transaction | ||||||
|  | from django.conf import settings | ||||||
| from django.core import mail | from django.core import mail | ||||||
| from django.core.management import call_command | from django.core.management import call_command | ||||||
| from django.test import _doctest as doctest | from django.test import _doctest as doctest | ||||||
| from django.test.client import Client | 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) | 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. |             * Flushing the database. | ||||||
|             * If the Test Case class has a 'fixtures' member, installing the  |             * If the Test Case class has a 'fixtures' member, installing the  | ||||||
|               named fixtures. |               named fixtures. | ||||||
|  |             * If the Test Case class has a 'urls' member, replace the | ||||||
|  |               ROOT_URLCONF with it. | ||||||
|             * Clearing the mail test outbox. |             * Clearing the mail test outbox. | ||||||
|         """ |         """ | ||||||
|         call_command('flush', verbosity=0, interactive=False) |         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 |             # We have to use this slightly awkward syntax due to the fact | ||||||
|             # that we're using *args and **kwargs together. |             # that we're using *args and **kwargs together. | ||||||
|             call_command('loaddata', *self.fixtures, **{'verbosity': 0}) |             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 = [] |         mail.outbox = [] | ||||||
|  |  | ||||||
|     def __call__(self, result=None): |     def __call__(self, result=None): | ||||||
| @@ -79,6 +87,23 @@ class TestCase(unittest.TestCase): | |||||||
|             result.addError(self, sys.exc_info()) |             result.addError(self, sys.exc_info()) | ||||||
|             return |             return | ||||||
|         super(TestCase, self).__call__(result) |         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, |     def assertRedirects(self, response, expected_url, status_code=302, | ||||||
|                         target_status_code=200, host=None): |                         target_status_code=200, host=None): | ||||||
|   | |||||||
| @@ -797,6 +797,37 @@ another test, or by the order of test execution. | |||||||
| .. _dumpdata documentation: ../django-admin/#dumpdata-appname-appname | .. _dumpdata documentation: ../django-admin/#dumpdata-appname-appname | ||||||
| .. _loaddata documentation: ../django-admin/#loaddata-fixture-fixture | .. _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 | Emptying the test outbox | ||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -318,3 +318,22 @@ class ExceptionTests(TestCase): | |||||||
|             self.client.get("/test_client_regress/staff_only/") |             self.client.get("/test_client_regress/staff_only/") | ||||||
|         except SuspiciousOperation: |         except SuspiciousOperation: | ||||||
|             self.fail("Staff should be able to visit this page") |             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/') | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user