Проверка перенаправления в Flask с помощью Python Unittest

В настоящее время я пытаюсь написать несколько модульных тестов для своего приложения Flask. Во многих моих функциях просмотра (например, при входе в систему) я перенаправляюсь на новую страницу. Так, например:

@user.route('/login', methods=['GET', 'POST'])
def login():
    ....
    return redirect(url_for('splash.dashboard'))

Я пытаюсь убедиться, что это перенаправление происходит в моих модульных тестах. Прямо сейчас у меня есть:

def test_register(self):
    rv = self.create_user('John','Smith','[email protected]', 'helloworld')
    self.assertEquals(rv.status, "200 OK")
    # self.assert_redirects(rv, url_for('splash.dashboard'))

Эта функция гарантирует, что возвращаемый ответ равен 200, но последняя строка явно имеет неверный синтаксис. Как я могу утверждать это? Моя функция create_user проста:

def create_user(self, firstname, lastname, email, password):
        return self.app.post('/user/register', data=dict(
            firstname=firstname,
            lastname=lastname,
            email=email,
            password=password
        ), follow_redirects=True)

person Jason Brooks    schedule 18.04.2014    source источник


Ответы (4)


Попробуйте Flask-Testing

есть API для assertRedirects, вы можете использовать это

assertRedirects(response, location)

Checks if response is an HTTP redirect to the given location.
Parameters: 

    response – Flask response
    location – relative URL (i.e. without http://localhost)

ТЕСТ Скрипт:

def test_register(self):
    rv = self.create_user('John','Smith','[email protected]', 'helloworld')
    assertRedirects(rv, url of splash.dashboard)
person kartheek    schedule 18.04.2014

Flask имеет встроенные крючки для тестирования и тестовый клиент, который отлично подходит для подобных функциональных вещей. .

from flask import url_for, request
import yourapp

test_client = yourapp.app.test_client()
with test_client:
    response = test_client.get(url_for('whatever.url'), follow_redirects=True)
    # check that the path changed
    assert request.path == url_for('redirected.url')

Для более старых версий Flask/Werkzeug запрос может быть доступен в ответе:

from flask import url_for
import yourapp

test_client = yourapp.app.test_client()
response = test_client.get(url_for('whatever.url'), follow_redirects=True)

# check that the path changed
assert response.request.path == url_for('redirected.url')

В документах есть дополнительная информация о том, как это сделать, хотя, к вашему сведению, если вы видите flaskr, это имя тестового класса, а не что-то в Flask, что меня смутило, когда я впервые увидел его.

person Rachel Sanders    schedule 18.04.2014
comment
Я настоятельно рекомендую людям использовать это решение, которое устраняет зависимость от Flask-Testing (в общем, я думаю, что использование как можно меньшего количества расширений — это хорошо, или только стабильные и большие, такие как Flask-Principal, Flask-Security и т. д. .). Однако это решение вызывает RuntimeError: Attempted to generate a URL without the application context being pushed. This has to be executed when application context is available, поскольку url_for требуется контекст приложения. Все, что вам нужно сделать, это поместить его в with app.app_context(): - person Edouard Berthe; 27.11.2016
comment
response.request --› AttributeError: объект «Ответ» не имеет атрибута «запрос» - person Calaf; 01.02.2019
comment
не уверен, что такое response.request, но если вы сохраните контекст запроса, используя with app.test_client() as c:, вы можете просто импортировать запрос и url_for и выполнить request.path == url_for(... - person DyRuss; 14.03.2019
comment
Судя по моим тестам, я не думаю, что использование request.path сработает, потому что путь установлен на начальный URL-адрес, а не на URL-адрес после перенаправления. @DyRuss - person Florent; 11.12.2019
comment
Из моих тестов я могу подтвердить, что использование клиента в качестве контекста (with client) изменяет контекст request при вызове client.get (и follow_redirects=True). Спасибо @DyRuss - person Bryce Guinta; 22.07.2020

Один из способов — не следовать перенаправлениям (либо удалить follow_redirects из запроса, либо явно установить для него значение False).

Затем вы можете просто заменить self.assertEquals(rv.status, "200 OK") на:

self.assertEqual(rv.status_code, 302)
self.assertEqual(rv.location, url_for('splash.dashboard', _external=True))

Если по какой-то причине вы хотите продолжать использовать follow_redirects, другой (слегка ненадежный) способ — проверить ожидаемую строку панели мониторинга, например идентификатор элемента HTML в ответе rv.data. например self.assertIn('dashboard-id', rv.data)

person broox    schedule 17.08.2014

Вы можете проверить окончательный путь после перенаправления с помощью тестового клиента Flask. в качестве менеджера контекста (используя with ключевое слово). Это позволяет сохранить окончательный контекст запроса, чтобы импортировать объект запроса , содержащий путь запроса.

from flask import request, url_for

def test_register(self):
    with self.app.test_client() as client:
        user_data = dict(
            firstname='John',
            lastname='Smith',
            email='[email protected]',
            password='helloworld'
        )
        res = client.post('/user/register', data=user_data, follow_redirects=True)
        assert res.status == '200 OK'
        assert request.path == url_for('splash.dashboard')
person Paweł Wamej    schedule 28.12.2019