Package: pytest-sanic
BuildDocsPackageA pytest plugin forSanic. It helps you to test your code asynchronously.This plugin provides:very easy testing with async coroutinescommon and useful fixturesasynchronous fixture supporttest_client/sanic_client for Sanic applicationtest_server for Sanic applicationYou 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/releasesInstallpip install pytest-sanicQuick StartYou don’t have to loadpytest-sanicexplicitly.pytestwill do it for you.You can set up a fixture for yourapplike this:importpytestfrom.appimportcreate_app@pytest.yield_fixturedefapp():app=create_app(test_config,**params)yieldappThisappfixture can then be used from tests:asyncdeftest_sanic_db_find_by_id(app):"""
    Let's assume that, in db we have,
        {
            "id": "123",
            "name": "Kobe Bryant",
            "team": "Lakers",
        }
    """doc=awaitapp.db["players"].find_by_id("123")assertdoc.name=="Kobe Bryant"assertdoc.team=="Lakers"To send requests to yourapp, you set up a client fixture using theloopandsanic_clientfixtures:@pytest.fixturedeftest_cli(loop,app,sanic_client):returnloop.run_until_complete(sanic_client(app))Thistest_clifixture can then be used to send requests to yourapp:asyncdeftest_index(test_cli):resp=awaittest_cli.get('/')assertresp.status_code==200asyncdeftest_player(test_cli):resp=awaittest_cli.get('/player')assertresp.status_code==200asynchronous fixturepytest-sanicalso supports asynchronous fixtures, just writes them like common pytest fixtures.@pytest.fixtureasyncdefasync_fixture_sleep():awaitasyncio.sleep(0.1)return"sleep..."FixturesSome fixtures for easy testing.looppytest-saniccreates an event loop and injects it as a fixture.pytestwill use this event loop to run yourasync tests.
By default, fixtureloopis an instance ofasyncio.new_event_loop. Butuvloopis also an option for you, by simpy passing--loopuvloop. Keep mind to just use one single event loop.unused_portan unused TCP port on the localhost.test_serverCreates a TestServer instance by giving aSanicapplication. It’s very easy to utilizetest_serverto create yourSanicapplication server for testing.@pytest.yield_fixturedefapp():app=Sanic("test_sanic_app")@app.route("/test_get",methods=['GET'])asyncdeftest_get(request):returnresponse.json({"GET":True})yieldapp@pytest.fixturedefsanic_server(loop,app,test_server):returnloop.run_until_complete(test_server(app))You can also very easily override thisloopfixture by creating your own, simply like,@pytest.yield_fixturedefloop():loop=MyEventLoop()yieldlooploop.close()test_clienttest_clienthas been deprecated, please usesanic_clientinstead, check outissuefor more context.sanic_clientCreates a TestClient instance by giving aSanicapplication. You can simply have a client by usingsanic_client, like@pytest.yield_fixturedefapp():app=Sanic("test_sanic_app")@app.route("/test_get",methods=['GET'])asyncdeftest_get(request):returnresponse.json({"GET":True})@app.route("/test_post",methods=['POST'])asyncdeftest_post(request):returnresponse.json({"POST":True})@app.route("/test_put",methods=['PUT'])asyncdeftest_put(request):returnresponse.json({"PUT":True})@app.route("/test_delete",methods=['DELETE'])asyncdeftest_delete(request):returnresponse.json({"DELETE":True})@app.route("/test_patch",methods=['PATCH'])asyncdeftest_patch(request):returnresponse.json({"PATCH":True})@app.route("/test_options",methods=['OPTIONS'])asyncdeftest_options(request):returnresponse.json({"OPTIONS":True})@app.route("/test_head",methods=['HEAD'])asyncdeftest_head(request):returnresponse.json({"HEAD":True})@app.websocket("/test_ws")asyncdeftest_ws(request,ws):data=awaitws.recv()awaitws.send(data)yieldapp@pytest.fixturedeftest_cli(loop,app,sanic_client):returnloop.run_until_complete(sanic_client(app,protocol=WebSocketProtocol))########## Tests ##########asyncdeftest_fixture_test_client_get(test_cli):"""
    GET request
    """resp=awaittest_cli.get('/test_get')assertresp.status_code==200resp_json=resp.json()assertresp_json=={"GET":True}asyncdeftest_fixture_test_client_post(test_cli):"""
    POST request
    """resp=awaittest_cli.post('/test_post')assertresp.status_code==200resp_json=resp.json()assertresp_json=={"POST":True}asyncdeftest_fixture_test_client_put(test_cli):"""
    PUT request
    """resp=awaittest_cli.put('/test_put')assertresp.status_code==200resp_json=resp.json()assertresp_json=={"PUT":True}asyncdeftest_fixture_test_client_delete(test_cli):"""
    DELETE request
    """resp=awaittest_cli.delete('/test_delete')assertresp.status_code==200resp_json=resp.json()assertresp_json=={"DELETE":True}asyncdeftest_fixture_test_client_patch(test_cli):"""
    PATCH request
    """resp=awaittest_cli.patch('/test_patch')assertresp.status_code==200resp_json=resp.json()assertresp_json=={"PATCH":True}asyncdeftest_fixture_test_client_options(test_cli):"""
    OPTIONS request
    """resp=awaittest_cli.options('/test_options')assertresp.status_code==200resp_json=resp.json()assertresp_json=={"OPTIONS":True}asyncdeftest_fixture_test_client_head(test_cli):"""
    HEAD request
    """resp=awaittest_cli.head('/test_head')assertresp.status_code==200resp_json=resp.json()# HEAD should not have bodyassertresp_jsonisNoneasyncdeftest_fixture_test_client_ws(test_cli):"""
    Websockets
    """ws_conn=awaittest_cli.ws_connect('/test_ws')data='hello world!'awaitws_conn.send(data)msg=awaitws_conn.recv()assertmsg==dataawaitws_conn.close()small notes:test_cli.ws_connectdoes not work insanic.__version__ <= '0.5.4', because of a Sanic bug, but it
has been fixed in master branch. Andwebsockets.__version__ >= '4.0'has broken websockets insanic.__version__ <= '0.6.0', but it has been fixed inmaster.TipsBlueprints Testingtest_cli.ws_connectdoes not work insanic.__version__ <= '0.5.4', because of a Sanic bug, but it has been fixed in master branch.Importing app has loop already runningwhen you havedb_initlisteners.Incorrect coverage reportwithpytest-cov, but we can have workarounds for this issue, it’s a pytest loading plugin problem essentially.Websockets > 4.0 has broken websockets insanic.__version__ <= '0.6.0', but it has been fixed inthis commitFeel free to create issue if you have any question. You can also check outclosed issuesDevelopmentpytest-sanicaccepts contributions on GitHub, in the form of issues or pull requests.Build.poetry installRun unit tests.poetry run pytest ./tests --cov pytest_sanicReferenceSome useful pytest plugins:pytest-tornadopytest-asynciopytest-aiohttp