【问题标题】:Django: Testing redirections when the target URL is also a redirectionDjango:当目标 URL 也是重定向时测试重定向
【发布时间】:2013-10-19 12:57:42
【问题描述】:

所以我正在编写一个分为多个部分的网站,这些部分本身又分为多个小部分。在我的设置中,当用户单击某个部分的链接(例如“/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')),
    ...
)

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 开发非常陌生,所以如果我在这里遗漏了一个明显的答案,我很抱歉。

【问题讨论】:

    标签: django unit-testing url-redirection


    【解决方案1】:

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

    断言响应 返回一个 status_code 重定向状态,它重定向到 expected_url (包括任何 GET 数据),最后一页收到 目标状态代码。

    如果您的请求使用了跟随参数,则 expected_url 和 target_status_code 将是最后一点的 url 和状态码 重定向链。

    来源:Django docs

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

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

    【讨论】:

    • 添加了target_status_code=301,测试运行良好。非常感谢!
    • @Ninethousand没问题,如果我的回答回答了你的问题,请将其标记为正确答案并点赞。谢谢!
    • 标记为正确,但我最近注册了,所以我还不能投票。以后有空我会回来的。
    • 所以要明确一点:在测试客户端的 get/post 请求中,您需要提供 Follow=True,然后在测试断言中,您可以保留 target_status_code=200(默认值)并提供预期/最终网址。对我来说这是可行的。
    【解决方案2】:

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

    self.assertRedirects(response, reverse('app:login'), fetch_redirect_response=False)
    

    【讨论】:

      猜你喜欢
      • 2016-01-27
      • 2013-02-13
      • 2015-02-04
      • 1970-01-01
      • 2018-09-24
      • 2013-02-04
      • 1970-01-01
      • 2021-12-25
      • 1970-01-01
      相关资源
      最近更新 更多