Skip to content
poly-crap
Esc
↑↓navigate↵open⌘Jpreview
On this page

How the score works

The CRAP formula, what follows from it, and how to choose a threshold for your code.

Poly-crap uses the Change Risk Anti-Patterns metric:

CRAP(m) = complexity(m)² × (1 - coverage(m) / 100)³ + complexity(m)

complexity is the function’s cyclomatic complexity: one, plus one for each decision point. Complexity rules lists what counts. coverage is the share of the function’s executable lines that a test ran.

Two things follow from the formula:

  • At 100% coverage the score equals the complexity. Coverage can only remove the first term, never the second, so a threshold also caps complexity.
  • The coverage term is cubed. Half coverage leaves an eighth of the penalty; 80% coverage leaves under 1%. The first tests on a function pay off the most.
Complexity 0% 50% 80% 100%
1 2.0 1.1 1.0 1.0
2 6.0 2.5 2.0 2.0
4 20.0 6.0 4.1 4.0
6 42.0 10.5 6.3 6.0
10 110.0 22.5 10.8 10.0

Choosing a threshold

The default threshold is 5. Under it, a function may have at most five decision points however well it is tested, a function with four needs more than 60% coverage, and a function with two needs about 10%. Poly-crap’s own repository holds itself to that number. It suits a small, well-tested codebase that wants to stay that way.

The threshold the metric’s authors proposed is 30. It tolerates a complexity of 30 when fully covered, or a complexity of 5 with no coverage at all. It suits an existing codebase that wants to catch the worst offenders first.

To pick one for your code:

  1. Run once with --min 0 to see every score, or --top 20 for the worst.
  2. Put a threshold you can meet today in .poly-crap.toml, and lower it as the code improves.
  3. Gate pull requests with --diff-base in the meantime, so new code meets the bar even where old code does not. A baseline does the same for the whole repository.

Last updated on September 6, 2026

Was this page helpful?