Metadata-Version: 2.4
Name: pytest-route-coverage
Version: 1.0.0
Summary: pytest plugin to generate reports on routes coverage for web applications.
Author: Felipe R. de Almeida
Author-email: Felipe R. de Almeida <felipe@owasp.org>
License-Expression: Apache-2.0
Requires-Dist: pytest>=7.2.2
Requires-Python: >=3.10
Project-URL: Homepage, https://github.com/feliperalmeida/pytest-route-coverage
Project-URL: Source, https://github.com/feliperalmeida/pytest-route-coverage
Project-URL: Issues, https://github.com/feliperalmeida/pytest-route-coverage/issues
Description-Content-Type: text/markdown

# pytest-route-coverage

A pytest plugin that tracks HTTP requests made during your test suite and tells you which routes were tested and which weren't.

## Supported Frameworks

Only **Django** is currently supported. You can open an issue (or a PR) if you'd like support for other frameworks.

## Installation

```
pip install pytest-route-coverage
```

## Usage

Run your tests with the `--route-coverage` flag:

```
pytest --route-coverage
```

This writes a `.route-coverage` JSON file to your project root. To see the report:

```
route-coverage show
```

Example output:

```
============================================================
Routes hit during tests
============================================================
  GET     /fakes/  [200]x1

  Total requests: 1
============================================================
Route coverage by test
============================================================
  GET     /fakes/
          - tests/test_views.py::test_list_fakes

============================================================
Untested routes
============================================================
  POST    /fakes/  (app/views.py)

  Untested: 1 route(s)
```

By default, all untested routes are shown. Pass `--tested-files-only` to limit the report to source files that had at least one route tested - useful when running a subset of tests:

```
route-coverage show --tested-files-only
```

## How it works

The plugin works by injecting a middleware into Django's middleware stack at the start of the test session. This middleware records every request that passes through it — method, path, status code, and which test triggered it.

This means it only captures requests that go through Django's full request/response cycle, i.e., tests that use `django.test.Client`, DRF's `APIClient`, or similar. If a test calls a view function directly, that request won't be recorded and the route will show up as untested. This is intentional: a direct function call doesn't exercise routing, middleware, authentication, or any of the other layers a real request would hit.

At the end of the session, the plugin walks Django's URL resolver to build a list of all registered DRF endpoints and writes everything to `.route-coverage`. The CLI then cross-references the request log against registered routes to find the gaps.

## pytest-xdist support

Works out of the box with `pytest-xdist`. Request logs from all workers are collected on the controller node and merged into a single results file.

```
pytest --route-coverage -n auto
```

## Parallel and append modes

For CI pipelines that split tests across multiple jobs:

```bash
# Each job writes its own file
pytest --route-coverage --route-coverage-parallel

# After all jobs finish, combine them
route-coverage combine

# Or accumulate results incrementally
pytest --route-coverage --route-coverage-append
```

`--route-coverage-parallel` writes to `.route-coverage.{hostname}.{pid}.{hex}` instead of the base file. `route-coverage combine` merges all suffix files into `.route-coverage` and cleans up the originals (pass `--keep` to preserve them).

`--route-coverage-append` merges new results into an existing `.route-coverage` file. These two flags are mutually exclusive.

## Development

```bash
uv sync --group dev
uv run pytest
```

### Running tests

Tests cover Django LTS and latest versions: 4.2, 5.2, and 6.0 (with and without xdist):

```
uv run tox
```

## License

Apache-2.0
