Testing ASGI applications made easy!
Why would you build this when all web frameworks come with one? Well, because mostly all those web frameworks have to build their own. I was building my own web framework perhaps (research & learning purpose) and got to the point where a needed a TestClient
but then a asked my self why does anybody building web frameworks have to build their own TestClient when there's a standard?. Ok, then just install starlette
a use it test client; would you install a library just to use a tiny part of it? This client does not have any dependencies.
Python 3.6+
It should run on Python 3.5 but I haven' tested it.
pip install asgi-testclient
The client replicates the requests API, so if you have used request you should feel comfortable. Note: the client method are coroutines get, post, delete, put, patch, etc..
.
import pytest
from asgi_testclient import TestClient
from myapp import API
@pytest.fixture
def client():
return TestClient(API)
@pytest.mark.asyncio
async def test_get(client):
response = await client.get("/")
assert response.json() == {"hello": "world"}
assert response.status_code == 200
I have used pytest
in this example but you can use whichever runner you prefer.
If you still prefer simple functions to coroutines, you can use the sync interface:
import pytest
from asgi_testclient.sync import TestClient
@pytest.fixture
def client():
return TestClient(API)
def test_get(client):
response = client.get("/")
assert response.json() == {"hello": "world"}
assert response.status_code == 200
Take in account that if you're running inside an async app you should use the async client, yet you can run the sync one inside threads is still desired.
If you're using ASGI you may be doing some web-sockets stuff. We have added support for it also, so you can test it easy.
from asgi_testclient import TestClient
from myapp import API
async def test_send():
echo_server = TestClient(API)
websocket = await echo_server.ws_connect("/")
for msg in ["Hey", "Echo", "Back"]:
await websocket.send_text(msg)
data = await websocket.receive_text()
assert data == msg
await websocket.close()
async def test_ws_context():
client = TestClient(API)
async with client.ws_session("/") as websocket:
data = await websocket.receive_text()
assert data == "Hello, world!"
Few things to take in count here:
- When using
ws_connect
you must callwebsocket.close()
to finish up your APP task. - For using websockets in context manager you must use
ws_session
instead ofws_connect
. - When waiting on server response
websocker.receive_*
it may raise aWsDisconnect
.
And one more time for those who don't want to this async we got the sync version:p
from asgi_testclient.sync import TestClient
from myapp import API
client = TestClient(API)
def test_send_receive_json():
websocket = client.ws_connect("/json")
json_msg = {"hello": "test"}
websocket.send_json(json_msg)
assert websocket.receive_json() == json_msg
websocket.close()
def test_ws_context():
with client.ws_session("/") as websocket:
data = websocket.receive_text()
assert data == "Hello, world!"
Important: In the sync version you cannot use send
or receive
since they're coroutines, instead use their children send_*
or receive_*
text|bytes|json
.
Also sync version is done throw monkey patching
so you can't use both version async & sync
at the same time.
- Support Websockets client.
- Cookies support.
- Redirects.
- Support files encoding
- Stream request & response
Tom Christie
: I brought inspiration from thestarlette
test client.Kenneth ☤ Reitz
: This package tries to replicaterequests
API.