Django:当目标URL也是重定向时测试重定向

时间:2013-10-11 12:31:47

标签: django unit-testing url-redirection

所以我正在编写一个分为几个部分的网站,这些网站本身分为几个小节。在我的设置中,当用户点击指向某个部分的链接时(比如说'/ home'),它们会被重定向到其中一个子部分(例如'/ home / cover')。此外,当用户转到页面根目录时,它们会被重定向到其中一个部分(在我的情况下为“/ home”)。有了这样的设置,当有人去根时发生的事情是,他们首先被重定向到'/ home',然后从那里重定向到'/ home / cover'。这些重定向是这样实现的:

主要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')),
    ...
)

组件/家/ 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'),
    ...
)

在实践中,这似乎工作正常:我可以浏览我的网站,所有重定向都可以做到。但是,我无法弄清楚如何为它们实现单元测试,特别是对于根重定向。

我最初设计的测试就像:

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

但是,当我运行它时,我遇到了错误:

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

现在,我可以轻松删除所有双重重定向,并使每个重定向的URL直接指向其目标,但是当前配置感觉更干净,更容易维护,所以如果有某种方式我可以正确地测试它将是完美的。

我对Django和Web开发很新,所以如果我在这里错过了一个明显的答案,我很抱歉。

2 个答案:

答案 0 :(得分:21)

  

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

     

断言响应   返回status_code重定向状态,重定向到expected_url   (包括任何GET数据),并收到最后一页   target_status_code。

     

如果您的请求使用了follow参数,则expect_url和   target_status_code将是最终点的url和状态代码   重定向链。

     

来源:Django docs

双重定向没有坏处(除了额外的HTTP请求)。考虑到这一点,Django的断言还会测试重定向到的URL(如果它是本地URL)。它期望的默认响应代码是200,但是当你有双重定向时,即301,这就失败了。因此,为了使测试用例成功,断言重定向也重定向:

self.assertRedirects(response, '/home', status_code=301, target_status_code=301)

答案 1 :(得分:1)

默认情况下,Django的assertRedirects获取页面的状态代码并测试它是OK。您可以通过设置fetch_redirect_response=False

来停用此功能
self.assertRedirects(response, reverse('app:login'), fetch_redirect_response=False)