Zum Inhalt

Testing

Der Test-Client ermöglicht Ihnen die Verwendung httpx Requests werden an Ihre ASGI-Anwendung gesendet.

from starlette . responses import HTMLResponse (englisch)
von starlette . testclient import TestClient


async def app (scope , receive , send) :
    assert scope ' type ' ] = ' http'.
    Antwort = HTMLResponse ('<html><body>Hallo , Welt !</body></html>')
    Erhalte Antworten (Senden , Empfangen , Senden)


def test _ app () (Beispiel) :
    client = Testclient (Anwendung)
    Antwort = client . get ('/')
    assert response . status _ code = 200 Zeichen

Der Testclient ist mit der gleichen Schnittstelle konfrontiert wie jede andere httpx-Sitzung , insbesondere ist zu beachten , dass der Aufruf , der eine Anfrage stellt , nur ein Standardfunktionsaufruf ist und kein wartendes Objekt .

Sie können jede httpx-Standard - API verwenden , z . B . Authentifizierung , Verarbeitung von Sitzungs-Cookies oder Datei-Uploads .

Um beispielsweise Header auf TestClient festzulegen , können Sie dies wie folgt tun :

client = Testclient (Anwendung)

Legen Sie Header für zukünftige Anforderungen des Clients fest
Benutzer . headers = {"Authorization": "..."}
Antwort = client . get ("/" oder ")

# Setheaders für jeden Request getrennt
response = client . get ("/" , headers ={"Authorization": "..."}) [ Bearbeiten | Quelltext bearbeiten ]

Verwenden Sie beispielsweise TestClient , um Dateien zu senden :

client = Testclient (App) Bearbeiten

Ein einziges File senden
mit open (" beispiel.txt " , " rb ") as f :
    antworten =client.post("/form " für files ={"file": f})

# Mehrere Dateien senden
with open (" beispiel.txt " , " rb ") as f1 :
    mit open (" example.png " , " rb ") as f2 :
        Dateien = {"file1": f1, "file2": ("filename", f2, "image/png")}
        antworten =client.post(" Dateiendung " , files = files)

Für weitere Informationen können Sie sich die httpx-Dokumentation anschauen .

Standardmäßig löst TestClient alle Ausnahmen in Ihrer Anwendung aus und gelegentlich möchten Sie vielleicht den Inhalt einer 500 - Fehlerantwort testen , anstatt dem Client zu erlauben , eine Serverausnahme auszulösen In diesem Fall sollten Sie client = TestClient(app, raise_server_exceptions=False) verwenden .

!!! Achtung !

Wenn Sie die `TestClient` Der Lauf The `lifespan` Der Handler,
Sie müssen `TestClient` als Kontextmanager verwenden .
Wenn `TestClient` nicht installiert ist , können Sie mehr darüber erfahren
[hier](lifespan.md#running-lifespan-in-tests) hier .

Auswahl der Back-End

TestClient akzeptiert die Parameter backend(eine Zeichenfolge) und backend_options(ein Wörterbuch) Diese Optionen werden an anyio.start_blocking_portal() übergeben , weitere Informationen zu akzeptablen Backend-Optionen finden Sie in der anyio-Dokumentation standardmäßig unter Verwendung von asyncio und seinen Standardoptionen .

Es tut uns leid , dass die Bedeutung von "Trio" und "backend="trio"" im Originaltext nicht genau übersetzt werden kann Wenn Sie mehr Informationen über diese beiden Symbole zur Verfügung stellen können , werde ich versuchen , Ihnen eine genauere Übersetzung zu geben .

def test _ app () () (Übersetzung)
    mit TestClient (app , backend = " trio ") als Client :
       ...

verwenden soll. uvloop Betrieb. asyncio übermittelt werden muss backend_options={"use_uvloop": True} Zum Beispiel:

def test _ app () () (Übersetzung)
    mit TestClient (app, backend_options =){"use_uvloop": True}(als Kunde: )
       ...

Testen einer WebSocket-Sitzung

Sie können auch den Testclient zum Testen von WebSocket-Sitzungen verwenden .

httpx Die Bibliothek wird zum Erstellen eines anfänglichen Handshakes verwendet , was bedeutet , dass Sie die gleichen Authentifizierungsoptionen und andere Header zwischen HTTP - und WebSocket-Tests verwenden können .

von starlette . testclient import TestClient
from starlette . websockets import WebSockets (englisch)


async def app (scope, receive, send):
    assert scope 'type']='websocket'.[Bearbeiten | Quelltext bearbeiten]
    WebSocket = WebSocket (scope, receive = receive, send = send)
    Websocket erstellen. accept ()
    await websocket. send_text ('Hello, world gaward')[Quelltext bearbeiten]
    websocket. close ()(schließen)


def test_app ()(Beispiel):
    client = Testclient (App) Bearbeiten
    mit client. websocket_connect ('/') as websocket:
        Daten = websocket. receive_text ()
        assert data =="Hallo Welt!"

Operationen in einer Sitzung sind Standardfunktionsaufrufe und keine wartbaren Objekte.

Die Verwendung von Sitzungen innerhalb eines kontextverwalteten with-Blocks ist wichtig, um sicherzustellen, dass der Hintergrundthread, in dem sich die ASGI-Anwendung befindet, ordnungsgemäß beendet wird und dass alle Ausnahmen, die innerhalb der Anwendung auftreten, immer vom Testclient ausgelöst werden.

Erstelle ein Testgespräch.

  • .websocket_connect(url, subprotocols=None, **options)-verwendet den gleichen Parametersatz wie httpx.get().

Wenn die Anwendung keine WebSocket-Verbindungen akzeptiert, kann starlette.websockets.WebSocketDisconnect ausgelöst werden.

websocket_connect() muss als Kontext-Manager (im with-Block) verwendet werden.

!!! Achtung! params Parameter sind nicht betroffen websocket_connect Support Wenn Sie Abfrageparameter übergeben müssen, setzen Sie sie direkt in die URL fest.

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

Senden von Daten

  • .send_text(data) - Der Text wird an die Anwendung gesendet.
  • .send_bytes(data) - Die angegebenen Bytes werden an die Anwendung gesendet.
  • .send_json(data, mode="text")-Gibt Daten an eine Anwendung mit mode="binary", um JSON über binäre Datenrahmen zu senden.

Empfangen von Daten

  • .receive_text() - Warten Sie auf den eingehenden Text, der von der Anwendung gesendet wird, und geben Sie ihn zurück.
  • .receive_bytes() - Warten Sie auf die eingehende Bytefolge, die von der Anwendung gesendet wird, und geben Sie sie zurück.
  • .receive_json(mode="text")- Warten auf eingehende JSON-Daten , die von der Anwendung gesendet werden , und deren Rückgabe mithilfe von mode="binary", um JSON über ein binäres Datenframe zu empfangen .

Der Text " May raise starlette.websockets.WebSocketDisconnect. " scheint weniger im Einklang mit dem regulären semantischen Ausdruck und schwierig , eine genaue chinesische Übersetzung zu machen Wenn Sie mehr kontextuelle Informationen haben oder die Richtigkeit des Textinhalts bestätigen , werde ich versuchen , Ihnen eine befriedigendere Übersetzung zu bieten derzeit nach wörtlicher Übersetzung , die nur übersetzt werden kann : " Vielleicht verbessern starlette.websockets.WebSocketDisconnect" , aber diese Übersetzung ist möglicherweise nicht ganz im Einklang mit der tatsächlichen Bedeutung .

Verbindungen schließen .

  • .close(code=1000) - Führt das Schließen der WebSocket-Verbindung durch den Client durch .

Ungleiche Proben .

Manchmal möchten Sie asynchrone Aktionen außerhalb der Anwendung ausführen , z . B . können Sie den Status einer Datenbank überprüfen , nachdem Sie Ihre Anwendung mit einem vorhandenen asynchronen Datenbankclient/- infrastruktur aufgerufen haben .

Für diese Fälle ist es schwierig ,TestClient zu verwenden , da es eine eigene Ereignisschleife erstellt und asynchrone Ressourcen (wie Datenbankverbindungen) oft nicht zwischen Ereignisschleifen geteilt werden können Der einfachste Weg , dieses Problem zu lösen , besteht darin , den gesamten Test asynchron zu machen und einen asynchronen Client wie httpx . AsyncClient zu verwenden .

Hier ist ein Beispiel für einen solchen Test :

from httpx import AsyncClient für Mac
von starlette . applications import Starlette
von starlette . routing import Route
from starlette . requests import Request (Eingabeaufforderung)
from starlette . responses import plainTextResponse (englisch)


def hello (request : Request) - > PlainTextResponse : Siehe auch :
    Die Antwort lautet : " Hello World ! " .


Starlette (Route = [ Route ("/" , hallo) ]) [ Bearbeiten | Quelltext bearbeiten ]


# Wenn Sie Pytest verwenden , müssen Sie einen Async-Marker wie hinzufügen :
@anyio # usinghttps://github.com/agronholm/anyio
# or install and configure pytest-asyncio (https://github.com/pytest-dev/pytest-asyncio) installieren und konfigurieren
async def test _ app () - > None : keine :
    #Zeichen: Du _muss_ Set `base_url` for relative urls like "/" zur Arbeit
    async mit AsyncClient (app = app , base _ url = " http://testserver ") als Client :
        r = await client . get ("/") (" wird angezeigt)
        assert r . status _ code = 200 Zeichen
        Text = = " Hallo Welt ! "