Skip to content
Latchkey

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.

python
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

  1. Set asyncio_mode so async tests actually execute.
  2. Declare the concurrency model to coverage.
  3. Re-run to confirm async routes now report coverage.
pyproject.toml
[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.

tests/test_api.py
def test_list_items(client):
    assert client.get("/items").status_code == 200

How to prevent it

  • Enable asyncio_mode so async tests truly run.
  • Declare the coverage concurrency model for async code.
  • Verify covered lines match the endpoints your tests call.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →