Перейти к содержанию

Тестирование

Тестирующий клиент позволяет вам использовать httpx Библиотека запрашивает приложение ASGI.

from starlette.responses import HTMLResponse
Testclient Import TestClient


async def app(scope, receive, send):
    assert scope ['type'] ='http'
    Response = HTMLResponse('<html><body>Hello, world!</body></html>')
    await response(scope, receive, send)


def test_app ():
    Client = TestClient(приложение)
    response = client.get ('/')
    assert response. status_code == 200

Тестирующий клиент обнаруживает тот же интерфейс, что и любой другой сеанс httpx. Обратите внимание, что запросы являются стандартными вызовами функции, а не ожидаемыми объектами.

Вы можете использовать любой стандартный API httpx, такой как аутентификация, обработка файлов Cookie сеанса или загрузка файлов.

Например, чтобы установить заголовок на TestClient, можно сделать следующее:

Client = TestClient(приложение)

# Set headers on the client for future requests
client headers = {"Authorization": "..."}
response = client.get ("/")

# Set headers for each request separately
response = client.get ("/", headers={"Authorization": "..."})

Например, отправка файлов с помощью TestClient:

Client = TestClient(приложение)

# Send a Single File
with open("example.txt", "rb") as f:
    response = client.post ("/form", files={"file": f})

Send Multiple Files
with open("example.txt", "rb") as f1:
    with open("example.png", "rb") as f2:
        files = files {"file1": f1, "file2": ("filename", f2, "image/png")}
        response = client.post ("/form", files=files)

Для получения дополнительной информации вы можете ознакомиться с документацией httpx.

По умолчанию TestClient вызывает любые исключения, которые появляются в приложении. Иногда вы можете проверить то, что отвечает на ошибку 500, вместо того, чтобы позволить клиенту генерировать исключения сервера. В этом случае вы должны использовать client = TestClient(app, raise_server_exceptions=False).

!!! Внимание!

Если ты хочешь `TestClient` Run the `lifespan` handler,
You will need to use the `TestClient` as a context manager. -It will
Not be triggered when the `TestClient` is instantiated. You can learn more about it
[here](lifespan.md#running-lifespan-in-tests)

Выбор асинхронного серба

TestClient принимает параметры backend(строка) и backend_options(словарь). Эти параметры передаются в anyio.start_blocking_portal(). Более подробную информацию о приемлемых параметрах бокса см. в документации anyio. По умолчанию используется asyncio и его параметры по умолчанию.

К сожалению, слова «Trio» и «backend="trio"» в оригинале не имеют точного значения и не могут быть переведены. Если вы можете предоставить больше информации об этих двух символах, я постараюсь предоставить вам точный перевод.

Def test_app (
    with TestClient(app, backend="trio") as client:
       ...

Чтобы запустить asyncio с помощью uvloop, необходимо передать backend_options={"use_uvloop": True}. Например:

Def test_app (
    with TestClient(app, backend_options ={"use_uvloop": True}) as client:
       ...

Тестирование сеансов WebSocket

Вы также можете использовать тестовый клиент для тестирования сеанса WebSocket.

httpx Библиотека будет использоваться для создания первоначального рукопожатия, что означает, что вы можете использовать одни и те же параметры аутентификации и другие заголовки между тестами http и websocket.

Testclient Import TestClient
Из Starlette.websockets import WebSocket


async def app(scope, receive, send):
    assert scope ['type'] ='websocket'
    WebSocket = WebSocket(scope, receive=receive, send=send)
    websocket.accept()
    await websocket.send_text ('Hello, world!')
    websocket.close (


def test_app ():
    Client = TestClient(приложение)
    with client.websocket_connect ('/') as websocket:
        data = websocket.receive_text (
        assert data = 'Hello, world!'

Действия в сеансе представляют собой стандартные вызовы функции, а не ожидание объектов.

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

Создание тестового сеанса

  • .websocket_connect(url, subprotocols=None, **options)-использует тот же набор параметров, что и httpx.get().

Если приложение не принимает подключение WebSocket, оно может запустить starlette.websockets.WebSocketDisconnect.

websocket_connect() должен использоваться в качестве контекстного менеджера (в блоке with).

!!! Обратите внимание, что параметры params не поддерживаются websocket_connect. Если вам нужно передать параметры запроса, строго закодируйте прямо в URL.

```python
with client.websocket_connect('/path?foo=bar') as websocket:
    ...
```

Отправить данные

  • .send_text(data) - Отправка данного текста в приложение.
  • .send_bytes(data) - Отправка заданного байта в приложение.
  • .send_json(data, mode="text")-Отправка данных в приложение. Используйте mode="binary" для отправки JSON через двоичные кадры данных.

Получение данных

  • .receive_text() - Дождитесь входящего текста, отправленного приложением, и верните его.
  • .receive_bytes() - Дождитесь входящей строки байтов, отправленной приложением, и верните ее.
  • .receive_json(mode="text")-ждать, пока входящие данные JSON отправятся приложением и вернутся. Используйте mode="binary", чтобы получить JSON через двоичные кадры данных.

Текст «May raise starlette.websockets.WebSocketDisconnect.» кажется менее подходящим для правильного перевода на китайский язык. Если у вас есть больше контекстной информации или подтверждение точности содержания текста, я постараюсь предоставить вам более удовлетворительный перевод. В настоящее время он может быть переведен только на «Может быть улучшен starlette.websockets.WebSocketDisconnect». Но этот перевод может быть не совсем реалистичным.

Закрытие соединения

  • .close(code=1000) - Выполните выключение клиентского соединения WebSocket.

Асинхронное тестирование

Иногда может потребоваться выполнить асинхронную операцию вне приложения. Например, можно проверить состояние базы данных после вызова приложения с помощью существующего клиента/инфраструктуры асинхронной базы данных.

В этих случаях использование TestClient является сложным, так как он создает собственный цикл событий, а асинхронные ресурсы, такие как подключение к базе данных, часто не могут быть совместно использованы между циклами событий. Самый простой способ решить эту проблему заключается в том, чтобы сделать весь тест асинхронным и использовать асинхронный клиент, такой как httpx.AsyncClient.

Вот пример такого тестирования:

Из http tpx import AsyncClient
Из Starlette.applications Import Starlette
От Starlet.routing Import Route
Из starlette.requests import Request
from starlette.responses import PlainTextResponse


def hello(request: Request) -> PlainTextResponse:
    Return PlainTextResponse(«Hello World!»)


app = Starlette(routes=[Route("/", hello)))


Если вы используете Pytest, You'll need to add an async marker like:
# @ pytest.mark.anyio # using https://github.com/agronholm/anyio
# or install and configure pytest-asyncio (https://github.com/pytest-dev/pytest-asyncio)
async def test_app () -> None
    #примечание: You _Must_ Set `base_url` "Для работы"/"Для работы"
    async with AsyncClient(app=app, base_url ="http://testserver") as client:
        r = await client ("/")
        assert r.status_code == 200
        assert r.text =«Hello World!»