Тестирование
Тестирующий клиент позволяет вам использовать 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!»