Build |
|
|---|---|
Docs |
|
Package |
A pytest plugin for Sanic. It helps you to test your code asynchronously.
This plugin provides:
very easy testing with async coroutines
common and useful fixtures
asynchronous fixture support
test_client/sanic_client for Sanic application
test_server for Sanic application
You can find out more here:
http://pytest-sanic.readthedocs.io/en/latest/
Releases and change logs can be found here:
https://github.com/yunstanford/pytest-sanic/releases
Install
pip install pytest-sanic
Quick Start
You don’t have to load pytest-sanic explicitly. pytest will do it for you.
You can set up a fixture for your app like this:
import pytest
from .app import create_app
@pytest.yield_fixture
def app():
app = create_app(test_config, **params)
yield app
This app fixture can then be used from tests:
async def test_sanic_db_find_by_id(app):
"""
Let's assume that, in db we have,
{
"id": "123",
"name": "Kobe Bryant",
"team": "Lakers",
}
"""
doc = await app.db["players"].find_by_id("123")
assert doc.name == "Kobe Bryant"
assert doc.team == "Lakers"
To send requests to your app, you set up a client fixture using the loop and sanic_client fixtures:
@pytest.fixture
def test_cli(loop, app, sanic_client):
return loop.run_until_complete(sanic_client(app))
This test_cli fixture can then be used to send requests to your app:
async def test_index(test_cli):
resp = await test_cli.get('/')
assert resp.status_code == 200
async def test_player(test_cli):
resp = await test_cli.get('/player')
assert resp.status_code == 200
asynchronous fixture
pytest-sanic also supports asynchronous fixtures, just writes them like common pytest fixtures.
@pytest.fixture
async def async_fixture_sleep():
await asyncio.sleep(0.1)
return "sleep..."
Fixtures
Some fixtures for easy testing.
loop
pytest-sanic creates an event loop and injects it as a fixture. pytest will use this event loop to run your async tests. By default, fixture loop is an instance of asyncio.new_event_loop. But uvloop is also an option for you, by simpy passing --loop uvloop. Keep mind to just use one single event loop.
unused_port
an unused TCP port on the localhost.
test_server
Creates a TestServer instance by giving a Sanic application. It’s very easy to utilize test_server to create your Sanic application server for testing.
@pytest.yield_fixture
def app():
app = Sanic("test_sanic_app")
@app.route("/test_get", methods=['GET'])
async def test_get(request):
return response.json({"GET": True})
yield app
@pytest.fixture
def sanic_server(loop, app, test_server):
return loop.run_until_complete(test_server(app))
You can also very easily override this loop fixture by creating your own, simply like,
@pytest.yield_fixture
def loop():
loop = MyEventLoop()
yield loop
loop.close()
test_client
test_client has been deprecated, please use sanic_client instead, check out issue for more context.
sanic_client
Creates a TestClient instance by giving a Sanic application. You can simply have a client by using sanic_client, like
@pytest.yield_fixture
def app():
app = Sanic("test_sanic_app")
@app.route("/test_get", methods=['GET'])
async def test_get(request):
return response.json({"GET": True})
@app.route("/test_post", methods=['POST'])
async def test_post(request):
return response.json({"POST": True})
@app.route("/test_put", methods=['PUT'])
async def test_put(request):
return response.json({"PUT": True})
@app.route("/test_delete", methods=['DELETE'])
async def test_delete(request):
return response.json({"DELETE": True})
@app.route("/test_patch", methods=['PATCH'])
async def test_patch(request):
return response.json({"PATCH": True})
@app.route("/test_options", methods=['OPTIONS'])
async def test_options(request):
return response.json({"OPTIONS": True})
@app.route("/test_head", methods=['HEAD'])
async def test_head(request):
return response.json({"HEAD": True})
@app.websocket("/test_ws")
async def test_ws(request, ws):
data = await ws.recv()
await ws.send(data)
yield app
@pytest.fixture
def test_cli(loop, app, sanic_client):
return loop.run_until_complete(sanic_client(app, protocol=WebSocketProtocol))
#########
# Tests #
#########
async def test_fixture_test_client_get(test_cli):
"""
GET request
"""
resp = await test_cli.get('/test_get')
assert resp.status_code == 200
resp_json = resp.json()
assert resp_json == {"GET": True}
async def test_fixture_test_client_post(test_cli):
"""
POST request
"""
resp = await test_cli.post('/test_post')
assert resp.status_code == 200
resp_json = resp.json()
assert resp_json == {"POST": True}
async def test_fixture_test_client_put(test_cli):
"""
PUT request
"""
resp = await test_cli.put('/test_put')
assert resp.status_code == 200
resp_json = resp.json()
assert resp_json == {"PUT": True}
async def test_fixture_test_client_delete(test_cli):
"""
DELETE request
"""
resp = await test_cli.delete('/test_delete')
assert resp.status_code == 200
resp_json = resp.json()
assert resp_json == {"DELETE": True}
async def test_fixture_test_client_patch(test_cli):
"""
PATCH request
"""
resp = await test_cli.patch('/test_patch')
assert resp.status_code == 200
resp_json = resp.json()
assert resp_json == {"PATCH": True}
async def test_fixture_test_client_options(test_cli):
"""
OPTIONS request
"""
resp = await test_cli.options('/test_options')
assert resp.status_code == 200
resp_json = resp.json()
assert resp_json == {"OPTIONS": True}
async def test_fixture_test_client_head(test_cli):
"""
HEAD request
"""
resp = await test_cli.head('/test_head')
assert resp.status_code == 200
resp_json = resp.json()
# HEAD should not have body
assert resp_json is None
async def test_fixture_test_client_ws(test_cli):
"""
Websockets
"""
ws_conn = await test_cli.ws_connect('/test_ws')
data = 'hello world!'
await ws_conn.send(data)
msg = await ws_conn.recv()
assert msg == data
await ws_conn.close()
small notes:
test_cli.ws_connect does not work in sanic.__version__ <= '0.5.4', because of a Sanic bug, but it has been fixed in master branch. And websockets.__version__ >= '4.0' has broken websockets in sanic.__version__ <= '0.6.0', but it has been fixed in master.
Tips
test_cli.ws_connect does not work in sanic.__version__ <= '0.5.4', because of a Sanic bug, but it has been fixed in master branch.
Importing app has loop already running when you have db_init listeners.
Incorrect coverage report with pytest-cov, but we can have workarounds for this issue, it’s a pytest loading plugin problem essentially.
Websockets > 4.0 has broken websockets in sanic.__version__ <= '0.6.0', but it has been fixed in this commit
Feel free to create issue if you have any question. You can also check out closed issues
Development
pytest-sanic accepts contributions on GitHub, in the form of issues or pull requests.
Build.
poetry install
Run unit tests.
poetry run pytest ./tests --cov pytest_sanic
Reference
Some useful pytest plugins:
Metadata
Release files for pytest-sanic 1.9.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pytest-sanic-1.9.1.tar.gz | 15.1 kB | Without provenance | Details for pytest-sanic-1.9.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pytest_sanic-1.9.1-py3-none-any.whl | Python 3 | none | any | Details for pytest_sanic-1.9.1-py3-none-any.whl |
Total release size: 27.6 kB
Release files / pytest-sanic-1.9.1.tar.gz
| Download URL | pytest-sanic-1.9.1.tar.gz |
|---|---|
| Size | 15.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
79daca07acbc0d9c1f9a1f0c7de7df92e159200e729c75e3a040366ff10a186a
|
|
BLAKE2b-256 checksum How to use checksums |
72ac4ee956ff836a8491d34c1cf198b91f859baee0374c9ae85767bb3debc59d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.0.3 CPython/3.8.1 Darwin/20.6.0
|
Release files / pytest_sanic-1.9.1-py3-none-any.whl
| Download URL | pytest_sanic-1.9.1-py3-none-any.whl |
|---|---|
| Size | 12.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a9a11f61dedbc3738c6a4f3d8ec24c42d48e25314ca1696f00782c7a0b3e1f16
|
|
BLAKE2b-256 checksum How to use checksums |
3c6756d797d6a835c701aea9be0e9e4e59ac43bb42f03c0d8268585a120257f0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.0.3 CPython/3.8.1 Darwin/20.6.0
|
Security for pytest-sanic 1.9.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.