tepyd gaps¶
Does the test tree structurally parallel the source tree?
gaps is a static, no-execution comparison of the test tree against the source tree, per tier, at the same granularity as your units, the slices shape and cover use. Refine the units patterns to make gaps coarser or finer; it never floods a deeply-nested project with per-sub-package findings.
Output¶
Mirror — test tree vs source tree (11 source units)
unit: 8/11 mirrored (73%)
gap cli
gap lenses/gaps
gap lenses/shape
integration: 5/5 mirrored (100%), 6 out of scope
e2e: 1/1 mirrored (100%), 10 out of scope
How to read it¶
For each tier, every unit falls into one of four buckets:
- present
- The unit has a matching test counterpart at this tier that actually contains tests. Counted in the
X/Y mirroredfigure. For a package unit that means a mirrored directory (checked recursively, so a test for any sub-package counts); for a module unit, atest_<stem>.pyfile. - gap
- A unit with no test counterpart at this tier that the tier was expected to test.
- out of scope
- A unit this tier is not responsible for, so its absence is reported as n/a. Shown as a count; the full list is in
--json. See layer awareness. - orphan
- A test directory that contains tests but has no source on disk: tests for code that moved or vanished.
Orphan detection asks whether the source actually exists, so it is independent of exclusions: excluded source still exists, so its tests are not orphans. Tests sitting directly at a tier root mirror nothing in particular and are never orphans.
Mapping is forward-only, from source unit to test location, honouring a tier's strip_prefix. That sidesteps the ambiguity of reversing a flattening map: orphans are found by asking which test directories are not expected, never by un-mapping them.
Scoping a tier to its layer¶
By default every tier is checked against every unit. That is fine for a flat app and noisy for a layered one:
unit: 4/10 mirrored (40%)
gap di
gap domain/ports
gap infrastructure
gap repositories
gap web
gap web/controllers
…and the integration and e2e tiers each report eight more in the same vein, all of it code that lives at a different tier. expects fixes this:
unit: 4/4 mirrored (100%), 4 out of scope
integration: 2/2 mirrored (100%), 6 out of scope
e2e: 2/2 mirrored (100%), 6 out of scope
A unit that should never be tested anywhere, such as a pure Protocol/ports layer with no runtime behaviour, belongs in exclude, which drops it from every tier.
Reading the figures¶
The figures are diagnostics, not targets. A browser tier showing 1/20 mirrored is often exactly right.