Skip to main content

No project description provided

Project description

pytest-sanic
============

.. image:: https://travis-ci.org/yunstanford/pytest-sanic.svg?branch=master
:alt: build status
:target: https://travis-ci.org/yunstanford/pytest-sanic

.. image:: https://coveralls.io/repos/github/yunstanford/pytest-sanic/badge.svg?branch=master
:alt: coverage status
:target: https://coveralls.io/github/yunstanford/pytest-sanic?branch=master


A pytest plugin for `Sanic <http://sanic.readthedocs.io/en/latest/>`_. It helps you to test your code asynchronously.

This plugin provides:

* very easy testing with async coroutines
* common and useful fixtures
* test_client for Sanic application
* test_server for Sanic application


-------
Install
-------

.. code::

pip install pytest-sanic


-----------
Quick Start
-----------

You don't have to load ``pytest-sanic`` explicitly. ``pytest`` will do it for you. Just write tests like,

.. code-block:: python

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"


--------
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.


``tmpdir``
~~~~~~~~~~~~~~

a temporary directory for easy testing if needed.


``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.

.. code-block:: python

@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,

.. code-block:: python

@pytest.yield_fixture
def loop():
loop = MyEventLoop()
yield loop
loop.close()


``test_client``
~~~~~~~~~~~~~~

Creates a TestClient instance by giving a ``Sanic`` application. You can simply have a client by using ``test_client``, like

.. code-block:: python

@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, test_client):
return loop.run_until_complete(test_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 == 200
resp_json = await 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 == 200
resp_json = await 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 == 200
resp_json = await 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 == 200
resp_json = await 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 == 200
resp_json = await 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 == 200
resp_json = await 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 == 200
resp_json = await 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_str(data)
msg = await ws_conn.receive()
assert msg.data == data
await ws_conn.close()

A small note: ``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.


-----------
Development
-----------

``pytest-sanic`` accepts contributions on GitHub, in the form of issues or pull requests.


Run unit tests.

.. code::

./uranium test


---------
Reference
---------

Some useful pytest plugins:

* `pytest-tornado <https://github.com/eugeniy/pytest-tornado>`_
* `pytest-asyncio <https://github.com/pytest-dev/pytest-asyncio>`_
* `pytest-aiohttp <https://github.com/aio-libs/pytest-aiohttp>`_

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pytest-sanic-0.1.3.tar.gz (8.0 kB view details)

Uploaded Source

Built Distribution

pytest_sanic-0.1.3-py2.py3-none-any.whl (13.0 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file pytest-sanic-0.1.3.tar.gz.

File metadata

File hashes

Hashes for pytest-sanic-0.1.3.tar.gz
Algorithm Hash digest
SHA256 332f6d487f85f20e01e636191a9d5e761cae9a872dede5bf8f3f1e1d0b4c989d
MD5 0cc50dade86068046f272235e01dd1ad
BLAKE2b-256 715c0f01acc48f952eb894ec2c0271789b9ff07df263fbf9592b27960e4084b5

See more details on using hashes here.

Provenance

File details

Details for the file pytest_sanic-0.1.3-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for pytest_sanic-0.1.3-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 a0e9c33fb7b024ac23b8c9c6b4ea8534803e6fee3b7610cea446b46dcae98a4a
MD5 008c68947cf6e5544780c8838a3f34a6
BLAKE2b-256 b9072d9f96d420c973c26bbde2a82558f7f5a0db2de9c2a401985a1b174b469a

See more details on using hashes here.

Provenance

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page