Django:测试页面是不是已重定向到所需的 url

Posted

技术标签:

【中文标题】Django:测试页面是不是已重定向到所需的 url【英文标题】:Django : Testing if the page has redirected to the desired urlDjango:测试页面是否已重定向到所需的 url 【发布时间】:2013-02-03 18:32:03 【问题描述】:

在我的 django 应用程序中,我有一个身份验证系统。因此,如果我没有登录并尝试访问某些个人资料的个人信息,我会被重定向到登录页面。

现在,我需要为此编写一个测试用例。我得到的浏览器的响应是:

GET /myprofile/data/some_id/ HTTP/1.1 302 0
GET /account/login?next=/myprofile/data/some_id/ HTTP/1.1 301 0
GET /account/login?next=/myprofile/data/some_id/ HTTP/1.1 200 6533

如何编写我的测试?这是我到目前为止所拥有的:

self.client.login(user="user", password="passwd")
response = self.client.get('/myprofile/data/some_id/')
self.assertEqual(response.status,200)
self.client.logout()
response = self.client.get('/myprofile/data/some_id/')

接下来会发生什么?

【问题讨论】:

【参考方案1】:

Django 1.4:

https://docs.djangoproject.com/en/1.4/topics/testing/#django.test.TestCase.assertRedirects

Django 2.0:

https://docs.djangoproject.com/en/2.0/topics/testing/tools/#django.test.SimpleTestCase.assertRedirects

SimpleTestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='', fetch_redirect_response=True)

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

如果您的请求使用 follow 参数,则 expected_urltarget_status_code 将是重定向最后点的 url 和状态码链。

如果 fetch_redirect_responseFalse,则不会加载最终页面。由于测试客户端无法获取外部 URL,因此如果 expected_url 不是您的 Django 应用程序的一部分,这将特别有用。

在两个 URL 之间进行比较时,会正确处理方案。如果在我们被重定向到的位置没有指定任何方案,则使用原始请求的方案。如果存在,expected_url 中的方案是用来进行比较的方案。

【讨论】:

【参考方案2】:

您也可以通过以下方式跟踪重定向:

response = self.client.get('/myprofile/data/some_id/', follow=True)

这将反映浏览器中的用户体验并断言您希望在那里找到的内容,例如:

self.assertContains(response, "You must be logged in", status_code=401)

【讨论】:

在测试中期望特定的页面内容是危险的。使非程序员(网页编辑)有可能在不知不觉中破坏测试。【参考方案3】:

您可以检查response['Location'] 并查看它是否与预期的网址匹配。还要检查状态码是否为 302。

【讨论】:

最适合不关心target_status_code 会是什么的情况。 直接对视图进行单元测试(不使用 Django 客户端)时,这是正确的答案。【参考方案4】:

response['Location'] 在 1.9 中不存在。改用这个:

response = self.client.get('/myprofile/data/some_id/', follow=True)
last_url, status_code = response.redirect_chain[-1]
print(last_url)

【讨论】:

如果没有提供follow=True,它可用的。 Django(任何版本)不会删除像Location 这样的正常响应头。当followTrue 时,将遵循重定向,自然最后的响应没有Location 标头。 我确认 Amir 是正确的 (Django 1.11.8),它允许使用 self.assertRedirects(或 status_code)检查重定向并检查重定向位置。【参考方案5】:

您可以使用 assertRedirects 例如:

response = self.client.get('/sekrit/')
self.assertRedirects(response, '/other/login/?next=/sekrit/')

https://docs.djangoproject.com/en/2.0/topics/testing/tools/#django.test.SimpleTestCase.assertRedirects

如果你需要获取重定向的url

如果followTrue

你会得到网址

response.redirect_chain[-1]

如果followFalse

response.url

【讨论】:

以上是关于Django:测试页面是不是已重定向到所需的 url的主要内容,如果未能解决你的问题,请参考以下文章

身份验证后重定向到所需页面[重复]

如何阻止 dojo 滚动到所需的输入

Laravel - 用户未通过身份验证时如何重定向到所需页面

重定向回页面时出错

ScrollTop 到所需的位置在 iPad 的情况下不起作用

如何计算呈现 Django 管理页面所需的 SQL 查询数?