Better Stack explains CRAP metric as Rust code quality gate gains attention
CRAP is getting real traction in Rust because it spots risky code paths that coverage alone misses. cargo-crap turns that idea into a practical gate for small teams.

CRAP lands in Rust because coverage alone keeps lying to you
A function can compile cleanly, pass tests, and still be the place where your next regression hides. That is the tension behind the new attention around CRAP, a metric that tries to answer a question Rust teams are asking more often now: which code looks safe on paper but is actually expensive to change?

Better Stack’s guide frames CRAP as a risk heuristic, not a badge of honor. That matters in Rust, where a tidy API surface can hide a nasty interior of branching logic, parser states, or old glue code that nobody wants to touch. The metric gets attention now because AI-assisted code generation can make codebases grow faster than the humans reading them, and the hard part is no longer whether the code compiles, but which paths are hardest to maintain once it does.
What CRAP measures, and why the formula matters
CRAP combines cyclomatic complexity with test coverage. Better Stack gives the formula as CRAP(m) = CC² × (1 - cov)³ + CC, where CC is cyclomatic complexity and cov is coverage expressed from 0 to 1. In plain terms, the score climbs when a function has many branches and not enough test coverage to prove those branches behave.
The important detail is that CRAP does not punish complexity by itself in a simplistic way. At 100% coverage, CRAP equals cyclomatic complexity, which means strong tests can cap risk, but they do not make complexity disappear. That is the whole point: a highly branched function with good coverage may still be worth keeping an eye on, but it should not trigger the same alarm as a complex function with weak tests.
That is why the metric is most useful as a triage tool. A small helper with low coverage may be acceptable if it has only a few paths and low change risk. A big parser, state machine, or feature switchboard with the same coverage profile is a very different story.
Where CRAP actually helps a solo or small-team Rust codebase
The best use case is not “measure everything and worship the dashboard.” It is “find the parts of the codebase that deserve the next hour of human attention.” In a solo project or a tiny team, that means CRAP can help you decide where to spend scarce review time.
Legacy modules are the obvious starting point. If you inherited a file with nested conditionals, conversion branches, and patches layered over years, the score gives you a quick way to separate “old but stable” from “old and dangerous.” A module with high complexity and low coverage is exactly the kind of place where a small refactor can quietly break behavior.
Weak tests are the second big win. Coverage alone tells you which lines were touched, but not whether the tests actually protect the risky logic inside those lines. CRAP makes that gap visible. If a function scores high, it is a sign that test count may look respectable while assertion depth is still thin.
Refactor triage is where the metric can save real time. When you are cleaning up a codebase, CRAP can help you decide which functions to freeze, which to split, and which to wrap in tests before touching anything else. It works best as a “do not refactor blind” marker, especially when you are trying to land changes without turning a weekend cleanup into a production incident.
The AI-assisted code angle is even more immediate. Generated Rust can be syntactically correct, idiomatic-looking, and still full of hidden branching complexity. CRAP gives you a way to ask whether the code paths added by an assistant are actually well exercised, which is more useful than simply asking whether the code compiled on the first try.
How cargo-crap turns the metric into a Rust workflow
This is where cargo-crap enters the picture. This Week in Rust named it crate of the week in issue 652 and described it as a cargo subcommand for calculating the Change Risk Anti-Patterns metric for a crate. That framing matters because it moves CRAP out of abstract discussion and into the everyday Rust tooling model.
The appeal is straightforward: if you already gather coverage data, cargo-crap lets you turn that data into a score you can act on. Instead of treating coverage as a detached report, you can pair it with complexity and use the output as part of a quality gate. That means a PR can be evaluated not just on whether tests exist, but on whether risky code paths are staying risky.
For a small team, that can be enough. You do not need a heavyweight quality platform to get value out of the idea. You need a repeatable check that points at the functions most likely to turn into refactor regrets.
When CRAP is a strong signal, and when it is just another number
CRAP helps when it changes behavior. If the score prompts you to add tests before a rewrite, split a sprawling function, or slow down before merging generated code, it is doing its job. It is especially useful in code with high branching, low assertion depth, or a lot of change pressure.
It becomes just another number when it is treated as a score to chase rather than a signal to inspect. A low score does not guarantee healthy design, and a high score does not automatically mean a function is broken. Rust developers already know that a lot of code quality work lives in context: ownership boundaries, module shape, API stability, and how painful a future change will be.
That is why the metric should be read as a map, not a verdict. It is good at showing where the road gets rough.
Why this idea is older than Rust, and why that history still matters
CRAP is not a fresh invention for the Rust world. Alberto Savoia and Bob Evans originally developed and launched it in 2007, and Savoia later explained that the name stands for Change Risk Anti-Patterns. Crap4j, the Java implementation, describes the metric as a combination of cyclomatic complexity and automated-test coverage aimed at code that is difficult to understand, test, or maintain.
Savoia also noted that the idea spread beyond Java into .NET, Ruby, PHP, Maven, Ant, and commercial tools such as Hudson’s Cobertura and Atlassian’s Clover. That history gives cargo-crap a useful kind of legitimacy: it is not inventing a new ideology around code quality, it is translating a long-running heuristic into Rust’s toolchain culture.
Martin Fowler’s long-standing point about coverage fits neatly here. Test coverage can help you find untested parts of a codebase, but it is a weak statement about test quality by itself. CRAP tries to bridge that gap by folding complexity into the picture, which is why it feels timely in Rust right now.
The reason cargo-crap is drawing attention is not that Rust suddenly needs another metric. It is that Rust teams, especially the small ones, need sharper ways to tell the difference between code that is merely covered and code that is actually safe to change. CRAP is useful when it points to that difference, and cargo-crap gives Rust a practical way to act on it.
This article was produced by Prism’s automated news system from verified source data, official records, and press releases, then run through automated quality and moderation checks before publishing. The system is built and supervised by the people who set the standards it runs under. Read our full AI policy.
Did this article answer your question?


