Python: pytest получает доступ к контекстным переменным Flask session и request.

Как включить методы pytest для доступа к контекстным переменным Flask, сессии и запросу.

Ранее я уже писал в блоге о приспособлении pytest для приложений и приспособлении для тестового клиента в Python: pytest и функциях контекстного процессора шаблона Flask. (См. раздел pytest entry module conftest.py).

Приспособление для тестового клиента в упомянутом посте:

@pytest.fixture(scope='module')
def test_client( app ):
    """
    Creates a test client.
    app.test_client() is able to submit HTTP requests.

    The app argument is the app() fixture above.    
    """

    with app.test_client() as testing_client:
        yield testing_client  # Return to caller.
Вход в полноэкранный режим Выход из полноэкранного режима

При тестировании кодов, которые обращаются к контекстной переменной Flask session, вышеуказанное приспособление работать не будет. Для доступа к этой переменной в официальном документе говорится следующее:

Если вы хотите получить доступ или установить значение в сессии до выполнения запроса, используйте метод session_transaction() клиента в операторе with. Он возвращает объект сессии и сохранит сессию после завершения блока.

https://flask.palletsprojects.com/en/2.2.x/testing/

Я пробовал это, и это не работает… Это «популярная» проблема. Она существует уже несколько лет. Есть несколько сообщений по ней, однако большинство предложений не работают для меня.

Сессии пусты при тестировании #69 поднимает эту проблему, а пользователь russmac предлагает решение:

@pytest.fixture(scope='module')
def test_client( app ):
    """
    Creates a test client.
    app.test_client() is able to submit HTTP requests.

    The app argument is the app() fixture above.    
    """

    with app.test_client() as testing_client:
        """
        See: https://github.com/pytest-dev/pytest-flask/issues/69 
        Sessions are empty when testing #69 
        """
        with testing_client.session_transaction() as session:
            session['Authorization'] = 'redacted'

        yield testing_client  # Return to caller.
Войти в полноэкранный режим Выйти из полноэкранного режима

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

with app.test_request_context():
Войти в полноэкранный режим Выйти из полноэкранного режима

Иначе возникает ошибка RuntimeError: Working outside of request context. Кроме того, без вышеуказанного вызова, собственно коды не смогут получить доступ к переменной запроса во время тестирования.

Ниже приведен правильный метод тестирования проекта, над которым я работаю:

@pytest.mark.timesheet_bro
def test_close( app ):
    bro_obj = TimesheetBRO( 1 )

    #
    # RuntimeError: Working outside of request context.
    #
    # session[ 'user_id' ] = 100
    #

    with app.test_request_context( '?searchType={}'.format(UNRESTRICT_SEARCH_TYPE) ):
        assert request.args[ 'searchType' ] == UNRESTRICT_SEARCH_TYPE
        assert request.values.get( 'searchType' ) == UNRESTRICT_SEARCH_TYPE

        session[ 'user_id' ] = 1

        data = bro_obj.close( 326 )

    assert bro_obj.last_message == ''
    assert data['status']['code'] == HTTPStatus.OK.value
Войти в полноэкранный режим Выход из полноэкранного режима

Обратите внимание, что в самом коде session[ ‘user_id’ ] устанавливается после того, как пользователь успешно вошел в систему. Установите это значение в тестовых кодах, чтобы создать правильное предусловие для тестируемых кодов. Обратите внимание, что request.values.get( ‘searchType’ ) также используется в тестируемых кодах.

Ниже приведен еще один правильный метод тестирования, который не передает никаких параметров запроса:

@pytest.mark.timesheet_bro
def test_update_last_timesheet_id( app ):
    bro_obj = TimesheetBRO( 1 )

    with app.test_request_context():
        session[ 'user_id' ] = 1

        data = bro_obj.update_last_timesheet_id( 1, 1123 )

    assert bro_obj.last_message == ''
    assert data['status']['code'] == HTTPStatus.OK.value
Войти в полноэкранный режим Выход из полноэкранного режима

Надеюсь, что в какой-то момент это будет вам полезно… И спасибо, что прочитали.

Оцените статью
devanswers.ru
Добавить комментарий