Tepyd — The TEst PYramid Doctor
Diagnose your test pyramid: is the shape what you say you want?
Tepyd looks at a project's test suite and tells you whether its shape matches the test pyramid you say you want: a broad base of cheap unit tests, fewer integration tests, a thin cap of end-to-end tests. It automates the checks you'd otherwise do by hand — which packages are under- or over-tested, where the cheap tests are missing, whether the test tree mirrors the source tree, and — by running your suite under coverage — which tier actually exercises each package.
It's configuration-driven: point it at any project, describe that project's layout once in pyproject.toml, and run one command.
Think
tepyd doctor: diagnose my pyramid.
The lenses
| Lens | Command | Question | Runs tests? |
|---|---|---|---|
| Shape | tepyd shape |
How much test code is there, and what shape does it make? | no |
| Gaps | tepyd gaps |
Does the test tree structurally parallel the source tree? | no |
| Cover | tepyd cover |
Which tier actually executes each unit — and is it the cheap one? | yes |
| Reach | tepyd reach |
Do unit-tier tests stay inside the unit under test? | no |
| Report | tepyd report |
The static checks at once, plus advice: the why and the how | no |
Install
uv sync # for development in this repo
# once published to PyPI (not yet):
# uv tool install tepyd
After uv sync, prefix commands with uv run (or activate the venv).
Quick start
uv run tepyd init # detect this project's layout, write a config
uv run tepyd report # the checks + advice, in one read
uv run tepyd shape --min-src 1 # every unit, including the small ones
uv run tepyd -C /path/to/project shape # analyse another project
uv run tepyd check # CI gate: silent + exit 0, or exit 1
Pyramid health: FAIR — 0 problem(s), 5 warning(s) across 11 unit(s).
• Tier mix: unit 60% / integration 26% / e2e 14% (target: unit ≥ 60%)
• Shape: 11 source units, weighted test/src 0.62x, unit share 60%.
• Gaps: unit tier mirrors 8/11 source packages; 0 orphan(s).
shape, gaps, reach and cover take --json; report renders text or Markdown via --format. All commands take -C/--root DIR. The lenses all exit 0 even with findings — tepyd check is the one command whose exit status is a verdict.
Requirements
- Python ≥ 3.10.
- No runtime dependencies on Python ≥ 3.11; on 3.10,
tomlibackports the stdlib'stomllib. shape,gaps,reachandreportneed nothing else — the line counter is built in.coveradditionally needs the analysed project's ownpytestandcoverageto be importable, so run it from that project's environment.clocis an optional opt-in for the line counter (counter = "cloc").
Documentation
Full docs live in docs/src:
- Getting started — install,
init, running the lenses, exit codes - Concepts — source units, tiers, unit share, shape glyphs, layer awareness
- The lenses — one page each, with its
--jsonshape - CI gate —
tepyd check, what fails a build and what doesn't - Configuration — the full
[tool.tepyd]reference
Build them locally with make docs, or make docs-serve for a live preview.
What Tepyd is not
- Not a test runner, and not a replacement for pytest or coverage —
coverorchestrates them. - Not a correctness checker. LOC is a proxy for effort, and a test's tier is decided by its directory, not by what it exercises.
- Not a pass/fail gate, except where you ask for one. The lenses report data and advice;
gapsandcoverfigures are diagnostics, not targets —1/20 mirroredfor a browser tier is often by design.tepyd checkis the opt-in gate, and it fires only on problems, never on advice.
Development
make test # pytest
make lint # ruff + ty + pyrefly + mypy
make format # ruff format + autofix
make docs # build the Zensical site
Tests are themselves organised as a pyramid (tests/a_unit, tests/b_integration, tests/c_e2e) — Tepyd eats its own dog food.
Changelog
See CHANGES.md.
License
Tepyd is licensed under the Apache License 2.0 — see LICENSE.
Metadata
Release files for tepyd 0.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tepyd-0.8.0.tar.gz | 51.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tepyd-0.8.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 111.0 kB
Release files / tepyd-0.8.0.tar.gz
| Download URL | tepyd-0.8.0.tar.gz |
|---|---|
| Size | 51.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ecf4cfac60cf8d4f86bf30b9fb7d80f4fda7c1720baf75a5ec368155a0635d47
|
|
BLAKE2b-256 checksum How to use checksums |
32b990dd67ee842e89fe55c83a630d49c00a14cbe52ed23cbcab98e53ec61a2f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / tepyd-0.8.0-py3-none-any.whl
| Download URL | tepyd-0.8.0-py3-none-any.whl |
|---|---|
| Size | 59.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0263ae0891c926d68c8e5d150572ce02dc23ddb396267157223bb6e3efb6c4f7
|
|
BLAKE2b-256 checksum How to use checksums |
ea624ce5363c05c6403be52177f83146d7a8228b88bfc1f18d202c7c07d89eef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|