Search code examples
djangopytestpytest-django

How to follow Django redirect using django-pytest?


In setting up a ArchiveIndexView in Django I am able to successfully display a list of items in a model by navigating to the page myself.

When going to write the test in pytest to verify navigating to the page "checklist_GTD/archive/" succeeds, the test fails with the message:

>       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

I understand there is a way to follow the request to get the final status_code. Can someone help me with how this done in pytest-django, similar to this question? The documentation on pytest-django does not have anything on redirects. Thanks.


Solution

  • UPDATE: I'm getting downvoted into oblivion but I still think my answer is better so let me explain.

    I still think there is a problem with Shacker's answer, where you can set follow=True and get a response code of 200 but not at the URL you expect. For example, you could get redirected unexpectedly to the login page, follow and get a response code of 200.

    I understand that I asked a question on how to accomplish something with pytest and the reason I'm getting downvoted is because I provided an answer using Django's built-in TestCase class. However, the correct answer for the test is/was more important to me at the time than exclusively using pytest. As noted below, my answer still works with pytest's test discovery so I think the answer is still valid. After all, pytest is built upon Django's built-in TestCase. And my answer asserts the response code of 200 came from where I expected it to come from.

    The best solution would be to modify pytest to include the expected_url as a parameter. If anyone is up for doing this I think it would be a big improvement. Thanks for reading.

    ORIGINAL CONTENT:

    Answering my own question here. I decided to include final expected URL using the built-in Django testing framework's assertRedirects and verify that it (1) gets redirected initially with 302 response and (2) eventually succeeds with a code 200 at the expected 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)
    

    Hat tip to @tdsymonds for pointing me in the right direction. I appreciated Shacker's answer but I have seen in some scenarios the redirect result being 200 when the page is redirected to an undesirable URL. With the solution above I am able to enforce the redirect URL, which pytest-django does not currently support.

    Please note: This answer is compliant with the auto-discover feature of pytest-django and is thus not incompatible (it will auto-discover both pytest-django and Django TestCase tests).