Unit test сеанс фляжи - не может воспроизвести сбой с session_transaction

Я тестирую приложение Flask (Flask 0.9), и, в частности, у меня есть сеансовое устройство, которое я хотел бы запустить документированным способом, будучи чем-то вроде этого (как я понимаю):

from flask import Flask, session
app = Flask(__name__)

@app.route('/', methods=['POST'])
def m():
    logging.error(session) # expect {'x': 1}
    return ""

with app.test_request_context() as trc:
  with app.test_client() as c:
    with c.session_transaction() as sess:
      sess['x'] = 1
    c.post()

Это работает так, как ожидалось, причем вывод выглядит примерно так:

ERROR:root:<SecureCookieSession {'x': 1}>

К сожалению, я столкнулся с неожиданным результатом, когда данные сеанса не установлены в функции конечной точки, то есть вывод выглядит примерно так:

ERROR:root:<SecureCookieSession {}>

Эта проблема проявляется только при запуске из моей модульной системы тестирования. Как бы то ни было, я не могу воспроизвести эту проблему с дегенеративным случаем, хотя я сделал довольно значительные усилия с сущностью некоторых из этих усилий здесь. Главным моментом является то, что я включил itsdangerous и Google App Engine testbed, ожидая, что, возможно, одна из них была причиной.

В моей собственной системе я пошел дальше, чем сущность, и почти полностью реплицировал мою инфраструктуру unit test, пытаясь ее изолировать. Аналогичным образом, я удалил все увеличивающиеся количества соответствующего кода из моей системы тестирования. К моменту, я не могу думать о различиях между вырожденным случаем и моей урезанной структурой, которая могла бы повлиять на результат. Я прошел через вызов c.post() в pdb, чтобы попытаться выяснить причину этой злости, но еще не получил полезной информации.

Что бы все сказать, я был бы благодарен за небольшое руководство или предложение относительно того, где может быть проблема. Что может повлиять на контекст Werkzeug таким образом, что session_transaction не соблюдается?

Ответ 1

Вот что я сделал:

# Code that modifies the current `session`; we must be in a test context already.
headers = {}
with self.client.session_transaction():
    # Get the cookie that is sent to the browser to establish a connection
    # via a fake request.
    response = make_response()
    self.app.session_interface.save_session(self.app, session, response)
    headers['Cookie'] = response.headers.get('Set-Cookie', '')
self.client.post(..., headers=headers)  # also works for .get, .put, etc.

Ответ 2

В моем случае я автоматически удалял файлы cookie в определенный домен, загружая файл конфигурации. Обновляя конфигурацию "на лету", я смог получить файлы cookie для работы во время модульного тестирования. Установив для свойства SESSION_COOKIE_DOMAIN значение None, все домены (а именно localhost) могли устанавливать сеансы.

app.config.update(                                                     
    SESSION_COOKIE_DOMAIN = None                                                
)

Возможно, вы захотите поиграть с настройками конфигурации, описанными в Обработка конфигурации в документах.

Ответ 3

Я ненавижу воскресить старый вопрос, но я считаю, что я решил решение этой проблемы. Для тестирования попробуйте установить для своего сервера имя localhost:

app.config['SERVER_NAME'] = 'localhost'

Я изначально использовал Brian hack, но это решило проблему для меня.

Ответ 4

Без тестового теста, который на самом деле терпит неудачу, трудно сказать много чего. Все, о чем я могу думать, это то, что экземпляр TestClient, который вы используете, делает запрос отличным от того, который вы используете для настройки сеанса. Например. вы можете сделать gist неудачным, как ожидалось, с этим:

with self.app.test_client() as c:
    with c.session_transaction() as sess:
        sess['d'] = 1
    self.client.post()

Но поскольку это не тот случай или сущность, идите фигуру.