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

How to follow Django redirect using django-pytest?

在 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

我知道有一种方法可以按照请求获得最终结果 status_code。有人可以帮助我在 pytest-django 中如何完成此操作,类似于 this question? The documentation on pytest-django 在重定向上没有任何内容。谢谢

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

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

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

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

原始内容:

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

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)

向@tdsymonds 致敬,感谢他为我指明了正确的方向。我很欣赏 Shacker 的回答,但我看到在某些情况下,当页面被重定向到不受欢迎的 URL 时,重定向结果为 200。使用上面的解决方案,我可以强制执行重定向 URL、which pytest-django does not currently support

请注意:此答案符合 pytest-django 的 auto-discover 功能,因此并非不兼容(它将 auto-discover pytest-django 和 Django TestCase 测试)。

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

def test_something(admin_client):
    response = admin_client.get(url, follow=True)
    assert response.status_code == 200

如果您想以标准用户登录:

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

通过在其中任何一个中使用 follow=Trueresponse.status_code 将等于重定向后页面的 return 代码,而不是访问原始 URL.因此,它应该解析为 200,而不是 301。

我认为它没有记录在 pytest-django 中,因为该选项是从它从 (making requests) 继承的 Django 测试客户端继承的。