如何使用django-pytest跟随Django重定向?

Sco*_*les 3 django pytest pytest-django

在Django中设置ArchiveIndexView时,我可以通过自己导航至页面来成功显示模型中的项目列表。

当要在pytest中编写测试以验证导航到页面“ checklist_GTD / archive /”是否成功时,测试失败并显示以下消息:

>       assert response.status_code == 200
E       assert 301 == 200
E        +  where 301 = <HttpResponsePermanentRedirect status_code=301, "text/html; charset=utf-8", url="/checklist_GTD/archive/">.status_code

test_archive.py:4: AssertionError
Run Code Online (Sandbox Code Playgroud)

我了解有一种方法可以按照请求获取最终的status_code。有人可以帮我解决这个问题,如何在pytest-django中完成吗?pytest-django上文档在重定向上没有任何内容。谢谢。

sha*_*ker 6

pytest-django提供未经身份验证client和已登录的admin_client固定装置。确实简化了这种事情。假设您正在使用此刻是admin_client因为您只想尽可能轻松地测试重定向,而无需手动登录:

def test_something(admin_client):
    response = admin_client.get(url, follow=True)
    assert response.status_code == 200
Run Code Online (Sandbox Code Playgroud)

如果要登录标准用户:

def test_something(client):
    # Create user here, then:
    client.login(username="foo", password="bar")
    response = client.get(url, follow=True)
    assert response.status_code == 200
Run Code Online (Sandbox Code Playgroud)

通过follow=True在这两种方法中使用,response.status_code将等于重定向后页面的返回代码,而不是对原始URL的访问。因此,它应该解析为200,而不是301。

我认为它没有在pytest-django中记录,因为该选项是从其子类(发出请求)的Django测试客户端继承的。


Sco*_*les 0

更新:我被低估了,但我仍然认为我的答案更好,所以让我解释一下。

我仍然认为 Shacker 的答案有问题,您可以设置 follow=True 并获得 200 的响应代码,但不是您期望的 URL。例如,您可能会意外重定向到登录页面,关注并获得响应代码 200。

我知道我问了一个关于如何使用 pytest 完成某些事情的问题,而我被否决的原因是因为我使用 Django 的内置 TestCase 类提供了答案。然而,当时测试的正确答案对我来说比专门使用 pytest 更重要。如下所述,我的答案仍然适用于 pytest 的测试发现,因此我认为答案仍然有效。毕竟,pytest 是建立在 Django 内置 TestCase 之上的。我的回答断言 200 的响应代码来自我预期的位置。

最好的解决方案是修改 pytest 以包含作为expected_url参数。如果有人愿意这样做,我认为这将是一个很大的进步。谢谢阅读。

原创内容:

在这里回答我自己的问题。我决定使用内置的 Django 测试框架包含最终的预期 URL assertRedirects,并验证它 (1) 最初通过响应进行重定向,以及 (2) 最终在预期 URL 处302成功执行代码。200

from django.test import TestCase, Client

def test_pytest_works():
    assert 1==1

class Test(TestCase):
    def test_redirect(self):
        client = Client()
        response = client.get("/checklist_GTD/archive/")
        self.assertRedirects(response, "/expected_redirect/url", 302, 200)
Run Code Online (Sandbox Code Playgroud)

感谢 @tdsymmonds 为我指明了正确的方向。我很欣赏 Shacker 的回答,但我在某些情况下看到重定向结果是200当页面重定向到不需要的 URL 时。通过上面的解决方案,我可以强制执行重定向 URL,而 pytest-django 目前不支持.

请注意:这个答案符合自动发现功能pytest-django,因此并不不兼容(它将自动发现 pytest-django 和 Django TestCase 测试)。