# Тестирование { #testing } Благодаря [Starlette](https://www.starlette.dev/testclient/), тестировать приложения **FastAPI** легко и приятно. Тестирование основано на библиотеке [HTTPX](https://www.python-httpx.org), которая в свою очередь основана на библиотеке Requests, так что все действия знакомы и интуитивно понятны. Используя эти инструменты, Вы можете напрямую задействовать [pytest](https://docs.pytest.org/) с **FastAPI**. ## Использование класса `TestClient` { #using-testclient } /// info | Информация Для использования класса `TestClient` сначала установите [`httpx`](https://www.python-httpx.org). Убедитесь, что Вы создали [виртуальное окружение](../virtual-environments.md), активировали его, а затем установили пакет, например: ```console $ pip install httpx ``` /// Импортируйте `TestClient`. Создайте объект `TestClient`, передав ему в качестве параметра Ваше приложение **FastAPI**. Создайте функцию, название которой должно начинаться с `test_` (это стандарт из соглашений `pytest`). Используйте объект `TestClient` так же, как Вы используете `httpx`. Напишите простое утверждение с `assert` дабы проверить истинность Python-выражения (это тоже стандарт `pytest`). {* ../../docs_src/app_testing/tutorial001_py310.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, необходимо вызывать асинхронные функции (например, для подключения к базе данных с помощью асинхронного драйвера), то ознакомьтесь со страницей [Асинхронное тестирование](../advanced/async-tests.md) в расширенном руководстве. /// ## Разделение тестов { #separating-tests } В реальном приложении Вы, вероятно, разместите тесты в отдельном файле. Кроме того, Ваше приложение **FastAPI** может состоять из нескольких файлов, модулей и т.п. ### Файл приложения **FastAPI** { #fastapi-app-file } Допустим, структура файлов Вашего приложения похожа на ту, что описана на странице [Более крупные приложения](bigger-applications.md): ``` . ├── app │ ├── __init__.py │ └── main.py ``` В файле `main.py` находится Ваше приложение **FastAPI**: {* ../../docs_src/app_testing/app_a_py310/main.py *} ### Файл тестов { #testing-file } Также у Вас может быть файл `test_main.py` содержащий тесты. Он может находиться в том же Python-пакете (в той же директории с файлом `__init__.py`): ``` hl_lines="5" . ├── app │ ├── __init__.py │ ├── main.py │ └── test_main.py ``` Так как оба файла находятся в одной директории, для импорта объекта приложения из файла `main` в файл `test_main` Вы можете использовать относительный импорт: {* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} ...и писать дальше тесты, как и раньше. ## Тестирование: расширенный пример { #testing-extended-example } Теперь давайте расширим наш пример и добавим деталей, чтоб посмотреть, как тестировать различные части приложения. ### Расширенный файл приложения **FastAPI** { #extended-fastapi-app-file } Мы продолжим работу с той же файловой структурой, что и ранее: ``` . ├── app │ ├── __init__.py │ ├── main.py │ └── test_main.py ``` Предположим, что в файле `main.py` с приложением **FastAPI** есть несколько **операций пути**. В нём описана операция `GET`, которая может вернуть ошибку. Ещё есть операция `POST`, и она может вернуть несколько ошибок. Обе *операции пути* требуют наличия в запросе HTTP-заголовка `X-Token`. {* ../../docs_src/app_testing/app_b_an_py310/main.py *} ### Расширенный файл тестов { #extended-testing-file } Теперь обновим файл `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`. * Для передачи *HTTP-заголовков*, передайте объект `dict` через параметр `headers`. * Для передачи *cookies* также передайте `dict`, но через параметр `cookies`. Для получения дополнительной информации о передаче данных на бэкенд с помощью `httpx` или `TestClient` ознакомьтесь с [документацией HTTPX](https://www.python-httpx.org). /// info | Информация Обратите внимание, что `TestClient` принимает данные, которые можно конвертировать в JSON, но не модели Pydantic. Если в Ваших тестах есть модели Pydantic и Вы хотите отправить их в тестируемое приложение, то можете использовать функцию `jsonable_encoder`, описанную на странице [Кодировщик совместимый с JSON](encoder.md). /// ## Запуск { #run-it } Далее Вам нужно установить `pytest`. Убедитесь, что Вы создали [виртуальное окружение](../virtual-environments.md), активировали его, а затем установили пакет, например: