Как следить за перенаправлением Django с помощью django-pytest?

При настройке ArchiveIndexView в Django я могу успешно отобразить список элементов в модели, самостоятельно перейдя на страницу.

Когда вы собираетесь написать тест в 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

Я понимаю, что есть способ выполнить запрос, чтобы получить окончательный код состояния. Может ли кто-нибудь помочь мне с тем, как это делается в pytest-django, аналогично этот вопрос? В документации по pytest-django ничего не говорится о перенаправлениях. Спасибо.


person Scott Skiles    schedule 09.01.2018    source источник
comment
Это помогает? docs.djangoproject.com/en/2.0 /topics/тестирование/инструменты/   -  person tdsymonds    schedule 09.01.2018
comment
Использование «assertRedirects» может быть хорошим решением, чтобы попробовать … но это будет включать в себя смешивание в тесте из django, а не использование существующего приспособления из «pytest-django». Если это единственный способ, я не удивлюсь! Но я смотрю, не упускаю ли я что-то очень простое, например, просто добавляю декоратор к функции.   -  person Scott Skiles    schedule 09.01.2018


Ответы (2)


pytest-django предоставляет как неаутентифицированные client, так и зарегистрированные 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=True в любом из них response.status_code будет соответствовать коду возврата страницы после перенаправления, а не доступу к исходному URL-адресу. Следовательно, он должен разрешаться в 200, а не в 301.

Я думаю, что это не задокументировано в pytest-django, потому что параметр унаследован от тестового клиента Django, из которого он является подклассом (запросы).

person shacker    schedule 21.03.2018
comment
У вас есть идеи, почему этого параметра «follow» нет в документации pytest-django? Если вы заметили выше в моем вопросе, я сослался на тот факт, что я ничего не видел о перенаправлении в документации, и это все еще так. pytest-django.readthedocs.io/en/latest/ - person Scott Skiles; 21.03.2018
comment
Отредактировал ответ, указав причину, по которой он не задокументирован. Но было бы неплохо увидеть это задокументированным — я уже вносил патчи для документации в pytest-django, и они были приняты. В любом случае, если вы нашли мой ответ полезным, отметьте его принятым или проголосуйте. - person shacker; 21.03.2018
comment
Ваш ответ великолепен и очень близок к тому, что я искал. Давайте посмотрим, сможем ли мы отредактировать его еще немного, если это возможно. В своем ответе ниже я указал, каким должен быть URL-адрес перенаправления. Есть ли способ сделать это с помощью параметра follow? Например, final_url или что-то подобное (например, response = admin_client.get(url, follow=True, final_url=/expected_redirect/url)?). Это будет полезно, если вы хотите убедиться, что вы правильно перенаправили неаутентифицированного клиента на страницу входа, а не на другую страницу, к которой у них не должно быть доступа. - person Scott Skiles; 22.03.2018
comment
Кроме того, вам не хватает закрывающей двойной кавычки () после полосы ниже (не позволит мне внести это тривиальное редактирование) - person Scott Skiles; 22.03.2018
comment
@ScottSkiles просто интересно, нашли ли вы способ подтвердить перенаправление только в pytest, используя что-то вроде assertRedirect? или вы в итоге импортировали из SimpleTestCase? - person bmeyer71; 13.08.2018
comment
Для справки, я все еще думаю, что есть проблема с этим ответом, когда вы можете установить follow=True и получить код ответа 200 но не по тому URL, который вы ожидаете. Например, вы можете неожиданно перенаправиться на страницу входа в систему, следуйте и получите код ответа 200, когда вы попадете на страницу входа в систему или что-то еще, когда вы ожидали чего-то другого. - person Scott Skiles; 30.05.2019

ОБНОВЛЕНИЕ: меня забрасывают в забвение, но я все еще думаю, что мой ответ лучше, поэтому позвольте мне объяснить.

Я все еще думаю, что есть проблема с ответом Шакера, где вы можете установить follow=True и получить код ответа 200, но не по тому URL-адресу, который вы ожидаете. Например, вы можете неожиданно перенаправиться на страницу входа, подписаться и получить код ответа 200.

Я понимаю, что задал вопрос о том, как что-то сделать с помощью pytest, и причина, по которой меня заминусовали, заключается в том, что я предоставил ответ, используя встроенный класс TestCase Django. Однако правильный ответ для теста в то время был для меня важнее, чем исключительно использование pytest. Как отмечено ниже, мой ответ по-прежнему работает с обнаружением тестов pytest, поэтому я думаю, что ответ все еще действителен. В конце концов, pytest построен на встроенном в Django TestCase. И мой ответ утверждает, что код ответа 200 пришел оттуда, откуда я ожидал.

Лучшим решением было бы изменить pytest, включив expected_url в качестве параметра. Если кто-то готов сделать это, я думаю, что это было бы большим улучшением. Спасибо за прочтение.

ОРИГИНАЛЬНОЕ СОДЕРЖАНИЕ:

Отвечая на мой собственный вопрос здесь. Я решил включить окончательный ожидаемый URL-адрес с помощью встроенной среды тестирования Django assertRedirects и убедиться, что он (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 за то, что указал мне правильное направление. Я оценил ответ Шакера, но я видел в некоторых сценариях результат перенаправления 200, когда страница перенаправляется на нежелательный URL-адрес. С помощью приведенного выше решения я могу применить URL-адрес перенаправления, который делает pytest-django в настоящее время не поддерживается.

Обратите внимание: этот ответ совместим с функцией автоматического обнаружения pytest-django и, следовательно, не является несовместимым (он автоматически обнаружит тесты pytest-django и Django TestCase).

person Scott Skiles    schedule 18.03.2018
comment
Отклонено, потому что предоставление нативных тестов Just use Django для человека, который задает вопрос о pytest, не особенно полезно. - person shacker; 21.03.2018
comment
Привет Шакер. Спасибо за объяснение. Я ответил на свой вопрос, если вы не заметили, из-за бездействия. И это по-прежнему решает проблему, потому что встроенное тестирование Django совместимо с командой pytest. Спасибо и за ваш ответ! Я проверю, работает ли он. - person Scott Skiles; 21.03.2018
comment
Из-за боязни, что меня заминусуют, я не буду делать это ответом. Но пока pytest-django полностью не поддерживает функцию перенаправления HTTP в SimpleTestCase, я просто добавляю URL-адреса с чем-то вроде assert response.url == reverse('login') + '?next=' + reverse('my_app:create'). - person highpost; 09.10.2019