Skip to content

Getting started

Install

Tepyd is on PyPI. Add it to the project you want to analyse:

$ uv add --dev tepyd

Then prefix commands with uv run (or activate the venv), as the examples on this site do.

To keep tepyd on your PATH instead, install it as a tool:

$ uv tool install tepyd

cover is different

The static lenses can be installed anywhere and pointed at any project with -C. cover imports and executes your code, so it must run from your project's environment. If you plan to use it, use uv add --dev tepyd rather than a tool install.

To work on Tepyd itself, run uv sync in a checkout.

Describe your layout

Tepyd needs to know two things: where your source is, and which directories are your test tiers. Rather than write that by hand, let Tepyd guess:

$ uv run tepyd init
Wrote [tool.tepyd] to /path/to/pyproject.toml.
  src_root = src/myapp   tiers: a_unit, b_integration, c_e2e
Review it, then run `tepyd shape` or `tepyd gaps`.

init looks for the usual clues: a src/ package or a flat top-level one, a tests/ tree split into tiers, a modules/ sub-layout, a top-level browser-test root. It then appends a commented [tool.tepyd] block to pyproject.toml, leaving the rest of the file untouched. It refuses to overwrite an existing [tool.tepyd] section.

Use --dry-run to see the block without writing it:

$ uv run tepyd init --dry-run

When init can't make a confident guess (several packages under src/, none named app or matching the project name), it asks you to choose, if it is running interactively. In a pipe or in CI it falls back to the first candidate and prints a note on stderr. Notes are also printed for anything else it had to guess.

Review the result before relying on it; Configuration is the full reference.

Run the lenses

$ uv run tepyd shape              # test LOC vs source LOC, per unit and per tier
$ uv run tepyd gaps               # which packages have no tests at which tier
$ uv run tepyd reach              # do unit tests stay inside their unit?
$ uv run tepyd cover              # which tier actually executes each unit (runs your suite)
$ uv run tepyd report             # all the static checks, with advice
$ uv run tepyd check              # the same checks as a CI gate: silent, or exit 1

Every command accepts -C/--root DIR to analyse a project other than the current directory:

$ uv run tepyd -C ../other-project shape

Small projects

shape, cover and report skip source units below 20 LOC by default. On a small codebase that can hide everything: pass --min-src 1 to see every unit.

Machine-readable output

shape, gaps, reach and cover take --json. That is the contract report builds on and the one to use for a CI check of your own:

$ uv run tepyd shape --json | jq '.[] | select(.unit_share < 0.4) | .name'

report renders prose, so it has no --json. It takes --format md for a PR comment or a committed file.

Exit codes

Code Meaning
0 Success. For the lenses, findings do not change this, since none of them is a gate. For check, it means no problems were found.
1 Nothing to analyse (no source units, or all below --min-src). The message says which.
2 Bad configuration, or an environment cover cannot run in.