9.9 KiB
Тестирование
Благодаря Starlette, тестировать приложения FastAPI легко и приятно.
Тестирование основано на библиотеке HTTPX, которая в свою очередь основана на библиотеке Requests, так что все действия знакомы и интуитивно понятны.
Используя эти инструменты, Вы можете напрямую задействовать pytest с FastAPI.
Использование класса TestClient
/// info | Информация
Для использования класса TestClient сначала установите httpx.
Убедитесь, что Вы создали виртуальное окружение{.internal-link target=_blank}, активировали его, а затем установили пакет, например:
$ pip install httpx
///
Импортируйте TestClient.
Создайте объект TestClient, передав ему в качестве параметра Ваше приложение FastAPI.
Создайте функцию, название которой должно начинаться с test_ (это стандарт из соглашений pytest).
Используйте объект TestClient так же, как Вы используете httpx.
Напишите простое утверждение с assert дабы проверить истинность Python-выражения (это тоже стандарт pytest).
{* ../../docs_src/app_testing/tutorial001.py hl[2,12,15:18] *}
/// tip | Подсказка
Обратите внимание, что тестирующая функция является обычной def, а не асинхронной async def.
И вызов клиента также осуществляется без await.
Это позволяет вам использовать pytest без лишних усложнений.
///
/// note | Технические детали
Также можно написать from starlette.testclient import TestClient.
FastAPI предоставляет тот же самый starlette.testclient как fastapi.testclient. Это всего лишь небольшое удобство для Вас, как разработчика. Но он берётся напрямую из Starlette.
///
/// tip | Подсказка
Если для тестирования Вам, помимо запросов к приложению FastAPI, необходимо вызывать асинхронные функции (например, для подключения к базе данных с помощью асинхронного драйвера), то ознакомьтесь со страницей Асинхронное тестирование{.internal-link target=_blank} в расширенном руководстве.
///
Разделение тестов
В реальном приложении Вы, вероятно, разместите тесты в отдельном файле.
Кроме того, Ваше приложение FastAPI может состоять из нескольких файлов, модулей и т.п.
Файл приложения FastAPI
Допустим, структура файлов Вашего приложения похожа на ту, что описана на странице Более крупные приложения{.internal-link target=_blank}:
.
├── app
│ ├── __init__.py
│ └── main.py
В файле main.py находится Ваше приложение FastAPI:
{* ../../docs_src/app_testing/main.py *}
Файл тестов
Также у Вас может быть файл test_main.py содержащий тесты. Можно разместить тестовый файл и файл приложения в одной директории (в директориях для Python-кода желательно размещать и файл __init__.py):
.
├── app
│ ├── __init__.py
│ ├── main.py
│ └── test_main.py
Так как оба файла находятся в одной директории, для импорта объекта приложения из файла main в файл test_main Вы можете использовать относительный импорт:
{* ../../docs_src/app_testing/test_main.py hl[3] *}
...и писать дальше тесты, как и раньше.
Тестирование: расширенный пример
Теперь давайте расширим наш пример и добавим деталей, чтоб посмотреть, как тестировать различные части приложения.
Расширенный файл приложения FastAPI
Мы продолжим работу с той же файловой структурой, что и ранее:
.
├── app
│ ├── __init__.py
│ ├── main.py
│ └── test_main.py
Предположим, что в файле main.py с приложением FastAPI есть несколько операций пути.
В нём описана операция GET, которая может вернуть ошибку.
Ещё есть операция POST, и она может вернуть несколько ошибок.
Обе операции пути требуют наличия в запросе заголовка X-Token.
{* ../../docs_src/app_testing/app_b_an_py310/main.py *}
Расширенный файл тестов
Теперь обновим файл test_main.py, добавив в него тестов:
{* ../../docs_src/app_testing/app_b_an_py310/test_main.py *}
Если Вы не знаете, как передать информацию в запросе, можете воспользоваться поисковиком (погуглить) и задать вопрос: "Как передать информацию в запросе с помощью httpx", можно даже спросить: "Как передать информацию в запросе с помощью requests", поскольку дизайн HTTPX основан на дизайне Requests.
Затем Вы просто применяете найденные ответы в тестах.
Например:
- Передаёте path-параметры или query-параметры, вписав их непосредственно в строку URL.
- Передаёте JSON в теле запроса, передав Python-объект (например:
dict) через именованный параметрjson. - Если же Вам необходимо отправить форму с данными вместо JSON, то используйте параметр
dataвместоjson. - Для передачи заголовков, передайте объект
dictчерез параметрheaders. - Для передачи cookies также передайте
dict, но через параметрcookies.
Для получения дополнительной информации о передаче данных на бэкенд с помощью httpx или TestClient ознакомьтесь с документацией HTTPX.
/// info | Информация
Обратите внимание, что TestClient принимает данные, которые можно конвертировать в JSON, но не модели Pydantic.
Если в Ваших тестах есть модели Pydantic и Вы хотите отправить их в тестируемое приложение, то можете использовать функцию jsonable_encoder, описанную на странице Кодировщик совместимый с JSON{.internal-link target=_blank}.
///
Запуск
Далее Вам нужно установить pytest.
Убедитесь, что Вы создали виртуальное окружение{.internal-link target=_blank}, активировали его, а затем установили пакет, например:
$ pip install pytest
---> 100%
Он автоматически найдёт все файлы и тесты, выполнит их и предоставит Вам отчёт о результатах тестирования.
Запустите тесты:
$ pytest
================ test session starts ================
platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /home/user/code/superawesome-cli/app
plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1
collected 6 items
---> 100%
test_main.py <span style="color: green; white-space: pre;">...... [100%]</span>
<span style="color: green;">================= 1 passed in 0.03s =================</span>