How to test redirection in Django using pytest?
Asked Answered
S

3

9

I already know that one can implement a class that inherits from SimpleTestCase, and one can test redirection by:

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

However, I am wondering what is the way I can check for redirection using pytest:

@pytest.mark.django_db
def test_redirection_to_home_when_group_does_not_exist(create_social_user):
    """Some docstring defining what the test is checking."""
    c = Client()
    c.login(username='TEST_USERNAME', password='TEST_PASSWORD')
    response = c.get(reverse('pledges:home_group',
                             kwargs={'group_id': 100}),
                     follow=True)
    SimpleTestCase.assertRedirects(response, reverse('pledges:home'))

However, I am getting the following error:

  SimpleTestCase.assertRedirects(response, reverse('pledges:home'))

E TypeError: assertRedirects() missing 1 required positional argument: 'expected_url'

Is there any way I can use pytest to verify redirection with Django? Or I should go the way using a class that inherits from SimpleTestCase?

Sumerlin answered 17/1, 2018 at 4:30 Comment(2)
Unrelated to your question, but if you're going to assert on a redirection you will want to pass follow=False not follow=True when you call c.get.Luiseluiza
@wim, thanks I guess I did it what you are suggesting in conjunction with the answer you provided.Sumerlin
L
6

This is an instance method, so it will never work like a class method. You should be able to simply change the line:

SimpleTestCase.assertRedirects(...)

into:

SimpleTestCase().assertRedirects(...)

i.e. we're creating an instance in order to provide a bound method.

Luiseluiza answered 17/1, 2018 at 4:40 Comment(4)
what do you mean by bound method? is it the same as an instance method?Sumerlin
@Luiseluiza is there a way to do the "assertRedirect" in pytest only, or is importing from SimpleTestCase the only way to test the url from a redirect?Harmonium
@Harmonium I would just pass follow=False in the client.get call and assert on the correct redirection status code (302) and/or the correct redirect url. Django's assertRedirects helper does too much, I avoid to use it really (it also checks that the redirected-to-URL is a 200 - I think that should be a put into a separate test if necessary - e.g., you might have a redirect to offsite resource and you don't want the tests to attempt to GET at that)Luiseluiza
@Luiseluiza Excellent! That is exactly what I was looking for. Thank you.Harmonium
I
8

I'm not an expert with pytest so probably is not elegant but you can check for the Location header like

test_whatever(self, user):
    client = Client()
    url = reverse('admin:documents_document_add')
    client.force_login(user)

    response = client.post(url, {<something>})

    # if the document is added correctly we redirect
    assert response.status_code == 302
    assert response['Location'] == reverse('admin:documents_document_changelist')
Inapposite answered 7/11, 2019 at 17:28 Comment(0)
L
6

This is an instance method, so it will never work like a class method. You should be able to simply change the line:

SimpleTestCase.assertRedirects(...)

into:

SimpleTestCase().assertRedirects(...)

i.e. we're creating an instance in order to provide a bound method.

Luiseluiza answered 17/1, 2018 at 4:40 Comment(4)
what do you mean by bound method? is it the same as an instance method?Sumerlin
@Luiseluiza is there a way to do the "assertRedirect" in pytest only, or is importing from SimpleTestCase the only way to test the url from a redirect?Harmonium
@Harmonium I would just pass follow=False in the client.get call and assert on the correct redirection status code (302) and/or the correct redirect url. Django's assertRedirects helper does too much, I avoid to use it really (it also checks that the redirected-to-URL is a 200 - I think that should be a put into a separate test if necessary - e.g., you might have a redirect to offsite resource and you don't want the tests to attempt to GET at that)Luiseluiza
@Luiseluiza Excellent! That is exactly what I was looking for. Thank you.Harmonium
D
0

You can use pytest_django.asserts.assertRedirects instead:

from pytest_django.asserts import assertRedirects

@pytest.mark.django_db
def test_redirection_to_home_when_group_does_not_exist(create_social_user):
    """Some docstring defining what the test is checking."""
    c = Client()
    c.login(username='TEST_USERNAME', password='TEST_PASSWORD')
    response = c.get(reverse('pledges:home_group',
                             kwargs={'group_id': 100}),
                     follow=True)
    assertRedirects(response, reverse('pledges:home'))
Dwan answered 8/11, 2023 at 17:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.