Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/oldani/asgi-testclient
Testing ASGI applications made easy!
https://github.com/oldani/asgi-testclient
asgi asyncio testing testing-tools webframework
Last synced: about 2 months ago
JSON representation
Testing ASGI applications made easy!
- Host: GitHub
- URL: https://github.com/oldani/asgi-testclient
- Owner: oldani
- License: mit
- Created: 2019-02-27T00:23:18.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2022-08-09T15:20:04.000Z (over 2 years ago)
- Last Synced: 2024-10-05T13:35:55.138Z (3 months ago)
- Topics: asgi, asyncio, testing, testing-tools, webframework
- Language: Python
- Size: 43.9 KB
- Stars: 11
- Watchers: 3
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# asgi-testClient
[![Build Status](https://travis-ci.org/oldani/asgi-testClient.svg?branch=master)](https://travis-ci.org/oldani/asgi-testClient)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/asgi-testClient.svg)
![PyPI](https://img.shields.io/pypi/v/asgi-testClient.svg)
[![codecov](https://codecov.io/gh/oldani/asgi-testClient/branch/master/graph/badge.svg)](https://codecov.io/gh/oldani/asgi-testClient)
![PyPI - Downloads](https://img.shields.io/pypi/dm/asgi-testClient.svg)
[![black](https://img.shields.io/badge/code_style-black-000000.svg)](https://github.com/ambv/black)Testing ASGI applications made easy!
## The why?
**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**.
## Requirements
`Python 3.6+`
It should run on Python 3.5 but I haven' tested it.
## Installation
`pip install asgi-testclient`
## Usage
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..`.
```python
import pytest
from asgi_testclient import TestClientfrom 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:
```python
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.**
## Websockets
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.
```python
from asgi_testclient import TestClient
from myapp import APIasync 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:
1. When using `ws_connect` you must call `websocket.close()` to finish up your APP task.
2. For using websockets in context manager you must use `ws_session` instead of `ws_connect`.
3. When waiting on server response `websocker.receive_*` it may raise a `WsDisconnect`.And one more time for those who don't want to this async we got the sync version:p
```python
from asgi_testclient.sync import TestClient
from myapp import APIclient = 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.
## TODO:
- [x] Support Websockets client.
- [ ] Cookies support.
- [ ] Redirects.
- [ ] Support files encoding
- [ ] Stream request & response## Credits
- `Tom Christie`: I brought inspiration from the `starlette` test client.
- `Kenneth ☤ Reitz`: This package tries to replicate `requests` API.