Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: Testing redirections when the target URL is also a redirection

So I'm programming a site divided in sections, which are themselves divided in subsections. In my setup, when a user clicks on the link to a section (let's say for instance '/home'), they are redirected to one of its subsections (e.g. '/home/cover'). Additionally, when a user goes to the page root, they are redirected to one of the sections (in my case '/home'). With that setup, what happens when someone goes to the root, is that they are first redirected to '/home', and from there to '/home/cover'. Those redirections are implemented like this:

Main urls.py:

from django.conf.urls import patterns, include, url
from django.views.generic.base import RedirectView

urlpatterns = patterns('',
    url(r'^$', RedirectView.as_view(url='/home')),
    url(r'^home/', include('components.home.urls', namespace='components.home')),
    ...
)

components/home/urls.py:

from django.conf.urls import patterns, include, url
from django.views.generic.base import RedirectView

from components.home import views

urlpatterns = patterns('',
    url(r'^$', RedirectView.as_view(url='cover')),
    url(r'^cover$', views.cover, name='home_cover'),
    ...
)

In practice, this seems to work fine: I can navigate my site and all the redirections do what they should. However, I can't figure out how to implement my unit tests for them, and in particular for the root redirection.

The test I designed originally was like:

def test_root_url_redirects_to_home_url(self):
    response = self.client.get('/')
    self.assertRedirects(response, '/home', status_code=301)

However, when I run it, I'm faced with the error:

"AssertionError: 301 != 200 : Couldn't retrieve redirection page '/home':
response code was 301 (expected 200)."

Now, I could easily remove all double redirections and make every redirected URL point directly to its target, but the current configuration feels cleaner and easier to maintain, so if there is some way I can properly test it that would be perfect.

I'm very new to Django and web development in general, so I'm sorry if I'm missing an obvious answer here.

like image 638
Ninethousand Avatar asked Oct 11 '13 12:10

Ninethousand


People also ask

Can we send data with redirect in Django?

You can now perform a redirect with Django, either by using the redirect response classes HttpResponseRedirect and HttpResponsePermanentRedirect , or with the convenience function django. shortcuts.

What is reverse redirect in Django?

Note − There is also a function to generate URLs; it is used in the same way as redirect; the 'reverse' method (django. core. urlresolvers. reverse). This function does not return a HttpResponseRedirect object, but simply a string containing the URL to the view compiled with any passed argument.


1 Answers

TestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='')

Asserts that the response return a status_code redirect status, it redirected to expected_url (including any GET data), and the final page was received with target_status_code.

If your request used the follow argument, the expected_url and target_status_code will be the url and status code for the final point of the redirect chain.

Source: Django docs

There is no harm in double redirection (aside from the extra HTTP requests). Bearing that in mind, Django's asserting also tests the redirected-to URL if it is a local URL. The default response code that it expects is 200, but as you have a double redirect, being the 301, this fails. So in order to make the test case succeed, is to assert that the redirect also redirects:

self.assertRedirects(response, '/home', status_code=301, target_status_code=301)
like image 173
Bouke Avatar answered Sep 21 '22 13:09

Bouke