tepyd shape¶
How much test code is there, and in what shape?
shape counts test LOC against source LOC for every source unit and reports the per-tier breakdown, the ratios, and the pyramid shape. It runs nothing and takes no measurable time.
$ tepyd shape
$ tepyd shape --json
$ tepyd shape --min-src 50 # skip source units under 50 LOC (default: 20)
$ tepyd shape --exclude faker # skip a unit, on top of config exclusions (repeatable)
Output¶
package src unit integration e2e tests ratio u%
-------------- --- ---- ----------- --- ----- ----- ---- -
core/discovery 97 180 0 0 180 1.86x 100% ▲
lenses/cover 491 332 109 0 441 0.90x 75% ▲
cli 304 0 0 240 240 0.79x 0% ▲
lenses/gaps 130 0 89 0 89 0.68x 0% ▲
core/loc 87 24 0 0 24 0.28x 100% ▲
=== Summary ===
Source units analysed : 11
Total source LOC : 2,700
Total test LOC : 1,706
unit : 1,020
integration : 446
e2e : 240
Weighted test/src : 0.63x (Σ tests / Σ src)
Plain mean ratio : 0.70x ± 0.38
Median ratio : 0.68x
Under-tested (0 < ratio < 0.5x — 4 units):
- lenses/report src= 586 tests= 169 ratio= 0.29x
...
Tier mix across the codebase : unit 60% / integration 26% / e2e 14%
✓ unit share is 100% (after setting aside 686 LOC of tests at their expected
higher tiers) — at or above the 60% target; tests live at their tiers.
Caveat : tier is by directory, not by what each test actually exercises.
How to read it¶
Each tier gets its own column, named by its label. Then:
src- Source LOC for the unit.
tests- Total test LOC across all tiers.
ratiotests / src. The summary calls out under-tested units (below0.5x) and heavily-tested ones (above2.0x). Those buckets are empirical: test/source ratios tend to be bimodal (rich suites cluster high, peripheral packages near zero), and IQR fences surface neither tail usefully.u%- How much of this unit's test code sits in the cheapest tier; see unit share.
—means there are no tests.
The last column is the shape glyph.
The summary also warns when the codebase-wide unit share falls below the first tier's target_share.
Layer-aware judging¶
If you have scoped your tiers with expects, shape respects it. A unit whose home is e2e, a web controller say, is not flagged ▼ for being e2e-heavy. The codebase target_share check also sets aside each unit's tests at its expected higher tiers before measuring. Only test mass sitting above where it belongs counts against you.
Without expects, nothing changes: every unit is judged against the classic unit-pyramid.
The caveat, stated up front¶
LOC is a proxy for effort. A test's directory decides its tier, whatever the test actually exercises. shape tells you where to look. cover tells you whether the tests are real.
--json¶
The payload is an array holding one object per unit: