From 4840fd9cbc3987781f7e6fab2520c9bd42aec057 Mon Sep 17 00:00:00 2001 From: Juan Catalano Date: Sat, 7 Sep 2013 18:13:57 -0300 Subject: [PATCH] Fixed #20919 -- Extended assertRedirects to be able to avoid fetching redirect's response. Thanks mjtamlyn for the suggestion. --- django/test/testcases.py | 21 ++++++++++++--------- docs/releases/1.7.txt | 5 +++++ docs/topics/testing/overview.txt | 8 +++++++- tests/test_client/tests.py | 4 ++++ tests/test_client/urls.py | 3 ++- tests/test_client/views.py | 3 +++ 6 files changed, 33 insertions(+), 11 deletions(-) diff --git a/django/test/testcases.py b/django/test/testcases.py index ab658a04fa..b90fafaf50 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -225,12 +225,14 @@ class SimpleTestCase(unittest.TestCase): return override_settings(**kwargs) 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 redirect URL can be loaded. 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: msg_prefix += ": " @@ -264,14 +266,15 @@ class SimpleTestCase(unittest.TestCase): url = response.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 - # to obtain the original response. - self.assertEqual(redirect_response.status_code, target_status_code, - msg_prefix + "Couldn't retrieve redirection page '%s':" - " response code was %d (expected %d)" % - (path, redirect_response.status_code, target_status_code)) + # Get the redirection page, using the same client that was used + # to obtain the original response. + self.assertEqual(redirect_response.status_code, target_status_code, + msg_prefix + "Couldn't retrieve redirection page '%s':" + " response code was %d (expected %d)" % + (path, redirect_response.status_code, target_status_code)) e_scheme, e_netloc, e_path, e_query, e_fragment = urlsplit( expected_url) diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt index 9f05055fd2..3e247fd211 100644 --- a/docs/releases/1.7.txt +++ b/docs/releases/1.7.txt @@ -293,6 +293,11 @@ Tests :attr:`~django.test.runner.DiscoverRunner.test_runner`, which facilitate 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 ===================================== diff --git a/docs/topics/testing/overview.txt b/docs/topics/testing/overview.txt index 7c6f5caa47..420401cd4a 100644 --- a/docs/topics/testing/overview.txt +++ b/docs/topics/testing/overview.txt @@ -1542,7 +1542,7 @@ your test suite. You can use this as a context manager in the same way as :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 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 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) Asserts that the strings ``html1`` and ``html2`` are equal. The comparison diff --git a/tests/test_client/tests.py b/tests/test_client/tests.py index 85637b982e..6525882663 100644 --- a/tests/test_client/tests.py +++ b/tests/test_client/tests.py @@ -405,6 +405,10 @@ class ClientTest(TestCase): # 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): "Request a page that modifies the session" # Session value isn't set initially diff --git a/tests/test_client/urls.py b/tests/test_client/urls.py index 4d2f4fb86e..693c7de2e1 100644 --- a/tests/test_client/urls.py +++ b/tests/test_client/urls.py @@ -29,5 +29,6 @@ urlpatterns = patterns('', (r'^session_view/$', views.session_view), (r'^broken_view/$', views.broken_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), ) diff --git a/tests/test_client/views.py b/tests/test_client/views.py index 08cdd8c198..35492238b8 100644 --- a/tests/test_client/views.py +++ b/tests/test_client/views.py @@ -257,3 +257,6 @@ def mass_mail_sending_view(request): c.send_messages([m1,m2]) return HttpResponse("Mail sent") + +def django_project_redirect(request): + return HttpResponseRedirect('https://www.djangoproject.com/')