Fixed #20919 -- Extended assertRedirects to be able to avoid fetching redirect's response.

Thanks mjtamlyn for the suggestion.
This commit is contained in:
Juan Catalano 2013-09-07 18:13:57 -03:00 committed by Tim Graham
parent 79ccd1a101
commit 4840fd9cbc
6 changed files with 33 additions and 11 deletions

View File

@ -225,12 +225,14 @@ class SimpleTestCase(unittest.TestCase):
return override_settings(**kwargs) return override_settings(**kwargs)
def assertRedirects(self, response, expected_url, status_code=302, def assertRedirects(self, response, expected_url, status_code=302,
target_status_code=200, host=None, msg_prefix=''): target_status_code=200, host=None, msg_prefix='',
fetch_redirect_response=True):
"""Asserts that a response redirected to a specific URL, and that the """Asserts that a response redirected to a specific URL, and that the
redirect URL can be loaded. redirect URL can be loaded.
Note that assertRedirects won't work for external links since it uses Note that assertRedirects won't work for external links since it uses
TestClient to do a request. TestClient to do a request (use fetch_redirect_response=False to check
such links without fetching thtem).
""" """
if msg_prefix: if msg_prefix:
msg_prefix += ": " msg_prefix += ": "
@ -264,14 +266,15 @@ class SimpleTestCase(unittest.TestCase):
url = response.url url = response.url
scheme, netloc, path, query, fragment = urlsplit(url) scheme, netloc, path, query, fragment = urlsplit(url)
redirect_response = response.client.get(path, QueryDict(query)) if fetch_redirect_response:
redirect_response = response.client.get(path, QueryDict(query))
# Get the redirection page, using the same client that was used # Get the redirection page, using the same client that was used
# to obtain the original response. # to obtain the original response.
self.assertEqual(redirect_response.status_code, target_status_code, self.assertEqual(redirect_response.status_code, target_status_code,
msg_prefix + "Couldn't retrieve redirection page '%s':" msg_prefix + "Couldn't retrieve redirection page '%s':"
" response code was %d (expected %d)" % " response code was %d (expected %d)" %
(path, redirect_response.status_code, target_status_code)) (path, redirect_response.status_code, target_status_code))
e_scheme, e_netloc, e_path, e_query, e_fragment = urlsplit( e_scheme, e_netloc, e_path, e_query, e_fragment = urlsplit(
expected_url) expected_url)

View File

@ -293,6 +293,11 @@ Tests
:attr:`~django.test.runner.DiscoverRunner.test_runner`, which facilitate :attr:`~django.test.runner.DiscoverRunner.test_runner`, which facilitate
overriding the way tests are collected and run. overriding the way tests are collected and run.
* The ``fetch_redirect_response`` argument was added to
:meth:`~django.test.SimpleTestCase.assertRedirects`. Since the test
client can't fetch externals URLs, this allows you to use ``assertRedirects``
with redirects that aren't part of your Django app.
Backwards incompatible changes in 1.7 Backwards incompatible changes in 1.7
===================================== =====================================

View File

@ -1542,7 +1542,7 @@ your test suite.
You can use this as a context manager in the same way as You can use this as a context manager in the same way as
:meth:`~SimpleTestCase.assertTemplateUsed`. :meth:`~SimpleTestCase.assertTemplateUsed`.
.. method:: SimpleTestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='') .. method:: SimpleTestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='', fetch_redirect_response=True)
Asserts that the response return a ``status_code`` redirect status, it Asserts that the response return a ``status_code`` redirect status, it
redirected to ``expected_url`` (including any GET data), and the final redirected to ``expected_url`` (including any GET data), and the final
@ -1552,6 +1552,12 @@ your test suite.
``target_status_code`` will be the url and status code for the final ``target_status_code`` will be the url and status code for the final
point of the redirect chain. point of the redirect chain.
.. versionadded:: 1.7
If ``fetch_redirect_response`` is ``False``, the final page won't be
loaded. Since the test client can't fetch externals URLs, this is
particularly useful if ``expected_url`` isn't part of your Django app.
.. method:: SimpleTestCase.assertHTMLEqual(html1, html2, msg=None) .. method:: SimpleTestCase.assertHTMLEqual(html1, html2, msg=None)
Asserts that the strings ``html1`` and ``html2`` are equal. The comparison Asserts that the strings ``html1`` and ``html2`` are equal. The comparison

View File

@ -405,6 +405,10 @@ class ClientTest(TestCase):
# TODO: Log in with right permissions and request the page again # TODO: Log in with right permissions and request the page again
def test_external_redirect(self):
response = self.client.get('/test_client/django_project_redirect/')
self.assertRedirects(response, 'https://www.djangoproject.com/', fetch_redirect_response=False)
def test_session_modifying_view(self): def test_session_modifying_view(self):
"Request a page that modifies the session" "Request a page that modifies the session"
# Session value isn't set initially # Session value isn't set initially

View File

@ -29,5 +29,6 @@ urlpatterns = patterns('',
(r'^session_view/$', views.session_view), (r'^session_view/$', views.session_view),
(r'^broken_view/$', views.broken_view), (r'^broken_view/$', views.broken_view),
(r'^mail_sending_view/$', views.mail_sending_view), (r'^mail_sending_view/$', views.mail_sending_view),
(r'^mass_mail_sending_view/$', views.mass_mail_sending_view) (r'^mass_mail_sending_view/$', views.mass_mail_sending_view),
(r'^django_project_redirect/$', views.django_project_redirect),
) )

View File

@ -257,3 +257,6 @@ def mass_mail_sending_view(request):
c.send_messages([m1,m2]) c.send_messages([m1,m2])
return HttpResponse("Mail sent") return HttpResponse("Mail sent")
def django_project_redirect(request):
return HttpResponseRedirect('https://www.djangoproject.com/')