FastAPI async code shows 0% coverage in CI
Coverage can under-report async route bodies when the concurrency model is not declared, or when async tests were collected but never awaited so the code never executed. The result is exercised endpoints showing as uncovered and a coverage gate failing.
What this error means
Coverage reports 0% or near-zero on async def handlers that tests clearly hit, and the coverage threshold check fails even though the endpoints work.
app/routes/items.py 40 38 5% 12-58
FAIL Required test coverage of 80% not reached. Total coverage: 41.00%Common causes
Async tests were not actually awaited
Without pytest-asyncio mode, async tests are collected but not run, so the route code never executes and shows no coverage.
Concurrency not declared to coverage
When code runs under a concurrency library, coverage needs it configured to attribute execution correctly.
How to fix it
Ensure async tests run, then configure concurrency
- Set
asyncio_modeso async tests actually execute. - Declare the concurrency model to coverage.
- Re-run to confirm async routes now report coverage.
[tool.coverage.run]
concurrency = ["greenlet", "thread"]
source = ["app"]Confirm the tests exercise the routes
Hit the endpoint through the client so the handler body runs and is measured.
def test_list_items(client):
assert client.get("/items").status_code == 200How to prevent it
- Enable
asyncio_modeso async tests truly run. - Declare the coverage concurrency model for async code.
- Verify covered lines match the endpoints your tests call.