Testing MicroPie applications¶
This guide shows practical approaches for testing MicroPie applications.
MicroPie does not ship with a bespoke test client, but because it is a
regular ASGI application you can exercise it using familiar Python
libraries such as unittest, pytest and
httpx’s ASGI tools.
Choosing a test framework¶
MicroPie itself uses unittest.IsolatedAsyncioTestCase in
tests.py to run asynchronous tests. pytest with the
pytest-asyncio plugin offers a similar developer experience. Pick the
library that best matches your project’s conventions—the examples below
work with either.
Unit testing handlers directly¶
Because handlers are regular functions, you can instantiate your
App subclass and call methods directly. Use the
micropie.current_request context variable to set up any request
state that your handler expects.
from micropie import App, Request, current_request
class MyApp(App):
async def greet(self, name="World"):
return f"Hello {name}!"
async def test_greet_uses_default():
app = MyApp()
scope = {"type": "http", "method": "GET", "path": "/"}
request = Request(scope)
token = current_request.set(request)
try:
response = await app.greet()
finally:
current_request.reset(token)
assert response == "Hello World!"
Testing through the ASGI interface¶
For higher confidence, drive the full ASGI stack. httpx provides an
ASGITransport class that can mount a MicroPie app. Install httpx
with pip install httpx. The example below uses pytest style
asserts, but the structure works in unittest with
self.assertEqual.
import pytest
import httpx
from micropie import App
class MyApp(App):
async def index(self):
return {"status": "ok"}
@pytest.mark.asyncio
async def test_index_returns_json():
app = MyApp()
async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app)) as client:
response = await client.get("http://test/")
assert response.status_code == 200
assert response.json() == {"status": "ok"}
Simulating sessions and middleware¶
To assert session behaviour, populate scope["headers"] with a
cookie header and inspect the response headers for the updated
Set-Cookie value. Middleware can be tested by attaching it to your
app instance before issuing requests.
import httpx
from micropie import App, HttpMiddleware
class AddHeader(HttpMiddleware):
async def before_request(self, request):
return None
async def after_request(self, request, status_code, response_body, extra_headers):
extra_headers.append(("X-Test", "1"))
return {"headers": extra_headers}
class MyApp(App):
async def index(self):
return "hi"
async def test_middleware_header():
app = MyApp()
app.middlewares.append(AddHeader())
transport = httpx.ASGITransport(app=app)
async with httpx.AsyncClient(transport=transport) as client:
response = await client.get("http://test/")
assert response.headers["x-test"] == "1"
Handling lifespan events¶
If your application registers startup or shutdown handlers, wrap your
ASGI client in a lifespan manager. httpx exposes
httpx.ASGITransport with a lifespan="auto" mode that will
run lifespan events before the first request and after the client exits
(on versions that support this option).
async with httpx.AsyncClient(
transport=httpx.ASGITransport(app=app, lifespan="auto")
) as client:
...
Further reading¶
Browse
tests.pyin the MicroPie source tree for additional patterns, including WebSocket testing helpers.The httpx documentation has more on driving ASGI apps from tests.