I remember sitting in a cold server room during a deployment at my old insurance firm, watching a CI pipeline crawl through three thousand green tests, only to have the system crash ten minutes later because of a simple database timeout. We had achieved 95% coverage, but we had completely missed the actual point. Most teams treat testing like a holy ritual where more is always better, but that’s a lie that leads to brittle suites and massive maintenance headaches. If you’re looking for a mathematical formula or a complex rubric for how to decide what not to test, you’re looking in the wrong place. Real engineering isn’t about hitting a percentage; it’s about knowing which failures actually matter.
I’m not here to sell you on a new testing framework or some academic theory of “optimal coverage.” Instead, I want to share the mental models I’ve built from a decade of fixing broken things in production. I’ll walk you through how I categorize risk, how to spot the “low-value” tests that just slow us down, and how to focus your energy on the edge cases that actually keep you awake at night. This is about being efficiently skeptical so you can ship code without the fear of a 2 AM phone call.
Table of Contents
Why Optimizing Test Coverage Is Often a Trap

The obsession with hitting a specific percentage of code coverage is one of the most expensive distractions in engineering. I’ve seen teams treat a 95% coverage metric like a holy grail, only to have the entire system go sideways because they spent all their energy testing trivial getters and setters while ignoring the actual state machine logic. When you focus purely on the number, you aren’t actually improving quality; you’re just performing a high-effort ritual. This kind of optimizing test coverage for the sake of a dashboard is a trap because it provides a false sense of security that evaporates the moment a real edge case hits production.
The real problem is that most automated suites suffer from a massive lack of software testing prioritization. We tend to write tests for the “happy path” because they are easy to write and they pass, which gives us that dopamine hit of a green build. But a green build doesn’t mean the system is safe; it just means you haven’t broken what you already thought you understood. Instead of chasing an arbitrary metric, I’ve learned that you have to perform a blunt cost-benefit analysis in QA. You need to ask: “If this specific line of code fails, does it trigger a P1 incident, or does it just make a UI element look slightly wonky?” If it’s the latter, stop wasting your CI minutes on it.
Using a Risk Based Testing Strategy to Sleep Better

Instead of chasing a magic percentage of code coverage, I’ve learned to look at the system through the lens of consequence. I call it a risk-based testing strategy, but in practice, it’s just asking myself: “If this specific function fails, does the company lose ten cents or ten thousand dollars?” There is a massive difference between a UI glitch in a settings menu and a race condition in the ledger service. One is a nuisance; the other is a phone call from the CTO at midnight.
To make this work, you have to stop treating every line of code as if it has equal importance. I try to perform a mental cost-benefit analysis in QA every time I add a new test. If a piece of logic is purely cosmetic or sits behind an administrative wall that no user ever touches, the effort required to maintain its tests often outweighs the actual risk.
The goal isn’t to be lazy; it’s about software testing prioritization that actually reflects reality. I’d rather have fifty rock-solid tests covering the critical path of our payment flow than five hundred tests that mostly just confirm the buttons are the right shade of blue. You focus your energy where the breakage actually hurts.
Five ways to prune your test suite without losing sleep
- Stop testing the third-party library. I’ve spent way too many hours writing integration tests for a client SDK only to realize the bug was actually in the vendor’s code all along. If you didn’t write the logic, don’t waste your CI minutes verifying it works as advertised; just test that your implementation handles their failure modes.
- Ignore the “happy path” vanity metrics. High code coverage looks great in a management dashboard, but a 95% coverage score is meaningless if it’s just testing that `1 + 1 = 2`. I’d rather have 40% coverage that hits the race conditions and database connection timeouts than 100% coverage that only validates the stuff that never actually breaks.
- If the cost of a failure is low, lower your testing bar. If a UI component renders a slightly wrong shade of blue in a dashboard that nobody looks at, that’s a bug, but it’s not a 2 AM incident. Don’t build a massive end-to-end suite for cosmetic features; save that energy for the payment processing logic.
- Kill the tests that have become “noise.” We all have those tests that fail randomly due to flaky network calls or timing issues, and then we just… ignore them. If a test fails once a week and you can’t fix it in an hour, delete it. A flaky test suite is worse than no test suite because it trains you to ignore the signals that actually matter.
- Don’t test your configuration. I once saw a team spend weeks writing unit tests to ensure their environment variables were being read correctly. That’s not a logic problem; that’s a deployment problem. Test the code that uses the config, but don’t build a complex testing ritual just to prove a string exists in a YAML file.
The TL;DR for your next sprint
Stop chasing 100% coverage as a vanity metric; if you’re testing a utility function that hasn’t changed in three years and has zero side effects, you’re just burning CI minutes and developer time for no reason.
Focus your energy on the “blast radius”—if a bug in a specific module means the payment gateway goes down or the database corrupts, that’s where your tests live; if it just breaks a UI tooltip, let it go.
Treat your test suite like a production system: if a test is flaky or constantly failing due to environmental noise rather than actual logic errors, delete it or fix it immediately, because a noisy test suite is just as dangerous as no test suite at all.
The Bottom Line

At the end of the day, deciding what not to test isn’t about being lazy; it’s about being intentional. I’ve learned the hard way that chasing 100% code coverage is usually just a way to hide from the real work. You have to weigh the cost of a test against the cost of a failure. If a bug in a specific module means a slightly weird UI element, let it go. If that same bug means a corrupted ledger in our payment gateway, you write the test, you run it in every pipeline, and you never let it slip. Focus on the critical paths and the high-stakes edge cases—the stuff that actually causes the pager to go off in the middle of the night.
My goal isn’t to build the most comprehensive test suite in the industry; it’s to build a system that is predictable and maintainable. Every test you add is a piece of technical debt you’re committing to maintain for the rest of the project’s life. Write only what is necessary to keep the system stable and your sanity intact. If you find yourself writing tests just to satisfy a metric, stop and ask yourself if you’re actually solving a problem or just polishing a dashboard. Go build something useful instead.
Frequently Asked Questions
How do I explain to a manager why we're intentionally leaving certain parts of the codebase without test coverage?
Don’t talk to them about “test coverage percentages”—that’s a vanity metric that leads to expensive, meaningless work. Instead, frame it as resource allocation. Tell them we aren’t skipping tests; we are prioritizing our engineering hours toward the parts of the system that actually carry financial or operational risk. I’d rather explain why we didn’t test a UI color change than explain why we didn’t test the payment gateway because we were too busy chasing 100% coverage on a trivial helper function.
At what point does "risk-based testing" just become an excuse for being lazy about technical debt?
It becomes an excuse the moment you stop documenting why you skipped something. Risk-based testing is a conscious trade-off; technical debt is just a debt you forgot you owed. If you’re skipping tests because the code is “too messy to test,” you aren’t managing risk—you’re just burying a landmine. I keep a running list of these “skipped” areas. If that list doesn’t eventually turn into a refactoring ticket, you’re just being lazy.
How do you handle the anxiety of knowing a bug is sitting in an untested area while you're trying to deploy?
I’ve been there. That knot in your stomach right before hitting “merge” is usually a signal that your mental model of the system is incomplete. I handle it by leaning on observability rather than perfection. If I can’t test a specific path, I make sure I can see it failing in real-time. I’ll add a custom metric or a specific alert for that area. If I can detect the fire immediately, I can sleep better.
If I decide to skip testing a specific service, how do I make sure that decision doesn't just get forgotten and become a ticking time bomb?
You don’t just “skip” it; you document the debt. I treat a skipped test like a known bug in a production log. If I decide a service doesn’t need integration tests because it’s a stateless utility, I put that decision in a `DECISIONS.md` file or a specific ADR (Architecture Decision Record). If it isn’t written down with a clear “why” and a “when to revisit,” it’s not a strategy—it’s just a mistake waiting to happen.
