cargo-grip4rust 0.1.3

A cargo subcommand for measuring Rust testability
Documentation

cargo-grip4rust

How much can tests grab onto your Rust codebase?

cargo-grip4rust is a static analysis tool that measures testability — how many clean entry points, pure functions, and trait seams a codebase exposes for testing. It produces a single grip score (0–100) with a per-module breakdown.


The problem

Most engineering orgs measure test coverage — how much code was exercised. But coverage tells you nothing about how hard it was to write those tests. A codebase can have 95% coverage and still be a nightmare to test:

  • Functions that smuggle hidden I/O (time, filesystem, randomness) as ambient dependencies
  • Concrete types everywhere, no trait seams for test doubles
  • Side effects mixed with computation, so you can't test logic without mocking the world
  • Everything private — zero public surface for test entry points

grip measures the root cause, not the symptom.


The formula (Phase 0)

pure_ratio   = probably_pure_functions / total_functions
public_ratio = public_items / total_items

grip = (pure_ratio × 0.6 + public_ratio × 0.4) × 100

A function is classified as probably pure when:

  • No &mut parameters
  • Returns a non-() value
  • Contains no unsafe blocks

A declaration is public when it's marked pub or pub(crate) — reachable from test code.

grip uses a heuristic for purity. It will produce false positives and false negatives. The heuristic is useful directionally: a module scoring 80 has more testability grip than one scoring 20. The limitation is stated explicitly — grip does not claim to detect purity, it estimates it.


Installation

cargo install cargo-grip4rust

Usage

cargo grip4rust [PATH]

Arguments:

Argument Description
[PATH] Path to Rust crate or workspace root (default: .)

Options:

Option Description
--json Emit structured JSON output
--threshold N Exit non-zero if overall grip score < N (CI gate). Alias: --min-score
-h, --help Print help
-V, --version Print version

Output

cargo-grip4rust 0.1.3 -- my-crate
══════════════════════════════════════════════════════

Overall grip score:    71 / 100
Public surface:        10 items
Total functions:       20
Probably pure:         12 / 20  (60.0%)

Per module:
  consensus                      grip:  78   pure: 71.4%   pub:  5
  transport                      grip:  83   pure: 78.9%   pub:  3
  timer                          grip:  44   pure: 31.2%   pub:  1  ❌
  state                          grip:  91   pure: 88.3%   pub:  6

Offenders (score < 50):
  timer                          grip:  44  ❌

JSON output (--json) includes the full breakdown and offenders list for CI pipelines, dashboards, and editor tooling.


What the score means

Range Meaning
80–100 High grip. Tests can reach most behavior through public surfaces and pure functions.
50–79 Moderate grip. Some modules are easy to test, others need refactoring.
20–49 Low grip. Most logic is hidden behind private items or mixed with side effects.
0–19 Minimal grip. The codebase resists testing at every level.

Roadmap

grip is being built in phases:

Phase What it adds Version
0 Public surface + pure function ratio v0.1.3
1 Trait boundary ratio (seams) v0.2.0
2 Hidden dependency detection v0.3.0
3 Testability Index (grip / braintax) v0.4.0
4 Git history tracking + Quality Index trend v1.0.0

See ROADMAP.md for the full plan.


Limitations

  • Purity is a heuristic. grip classifies functions by signature patterns, not by type inference. It will make mistakes at the margin.
  • No runtime analysis. grip never executes code, runs tests, or instruments builds.
  • No coverage data. grip measures testability, not testing. Use a coverage tool alongside it.

License

MIT — see LICENSE.