Metadata-Version: 2.4
Name: tepyd
Version: 0.8.0
Summary: TEst PYramid Doctor — diagnose a project's test pyramid: mass, structure, and coverage.
Author: Stefane Fermigier
Author-email: Stefane Fermigier <sf@abilian.com>
License-Expression: Apache-2.0
License-File: LICENSE
Requires-Dist: tomli>=2.0 ; python_full_version < '3.11'
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# 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`](docs/src/lenses/shape.md) | How much test code is there, and what shape does it make? | no |
| **Gaps** | [`tepyd gaps`](docs/src/lenses/gaps.md) | Does the test tree structurally parallel the source tree? | no |
| **Cover** | [`tepyd cover`](docs/src/lenses/cover.md) | Which tier actually *executes* each unit — and is it the cheap one? | **yes** |
| **Reach** | [`tepyd reach`](docs/src/lenses/reach.md) | Do unit-tier tests stay inside the unit under test? | no |
| **Report** | [`tepyd report`](docs/src/lenses/report.md) | The static checks at once, plus advice: the *why* and the *how* | no |

## Install

```bash
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

```bash
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`](docs/src/ci.md) is the one command whose exit status is a verdict.

## Requirements

- Python ≥ 3.10.
- No runtime dependencies on Python ≥ 3.11; on 3.10, `tomli` backports the stdlib's `tomllib`.
- `shape`, `gaps`, `reach` and `report` need nothing else — the line counter is built in.
- `cover` additionally needs the analysed project's own `pytest` and `coverage` to be importable, so run it from that project's environment.
- `cloc` is an optional opt-in for the line counter (`counter = "cloc"`).

## Documentation

Full docs live in [`docs/src`](docs/src/index.md):

- [Getting started](docs/src/getting-started.md) — install, `init`, running the lenses, exit codes
- [Concepts](docs/src/concepts.md) — source units, tiers, unit share, shape glyphs, layer awareness
- [The lenses](docs/src/lenses/index.md) — one page each, with its `--json` shape
- [CI gate](docs/src/ci.md) — `tepyd check`, what fails a build and what doesn't
- [Configuration](docs/src/configuration.md) — 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 — `cover` orchestrates 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; `gaps` and `cover` figures are diagnostics, not targets — `1/20 mirrored` for a browser tier is often by design. [`tepyd check`](docs/src/ci.md) is the opt-in gate, and it fires only on problems, never on advice.

## Development

```bash
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](CHANGES.md).

## License

Tepyd is licensed under the Apache License 2.0 — see [LICENSE](LICENSE).
