You've got a coverage dashboard showing green across the board, and it still didn't stop last week's bug from reaching production. That's not a fluke. Coverage tracks what your tests ran, not whether they checked anything meaningful, so a perfect score can sit right next to broken logic. We'll dig into what this metric is actually good for and why the goal isn't to max it out.
TLDR:
- Code coverage measures what lines ran, not whether results were correct or verified.
- Most teams target 70 to 90 percent, pushing payment and auth modules into the upper 90s.
- 100% coverage is achievable with zero assertions checking actual output or logic.
- Coverage tools miss integration, UI, and end-to-end flows that span screens and network calls.
- Minitap runs regression across real devices and interfaces, catching gaps unit coverage cannot reach.
What Is Code Coverage
Code coverage measures the percentage of your source code (lines, branches, or paths) that executes when your test suite runs. Eighty of 100 lines executed means 80% coverage on that file. The number reflects what ran, not whether the results were correct. A test can execute a line without checking anything meaningful about its output.
Teams track coverage anyway because it flags regression risk, feeds release readiness dashboards, and surfaces code that no quality assurance check has ever touched.
How Code Coverage Is Measured
Coverage tools insert tracking hooks into your code before it runs, a process called instrumentation, either at the source level with counters around each line or branch, or at the bytecode level after compiling. The instrumented build behaves like your normal one, just with extra bookkeeping. Understanding mobile app testing basics helps teams interpret what these reports actually mean.
From there, the process runs in three steps:

- Run your existing test suite against the instrumented build, unchanged.
- Each hook records whether its line, branch, or condition executed at least once.
- The tool aggregates hits into a report: a percentage per file, module, and codebase, with color coded output showing untouched lines.
The percentage gets the attention, but the line-by-line breakdown is what tells you where to write the next test.
Types Of Code Coverage Metrics
Line coverage is the simplest and most common metric: it counts how many executable lines ran at least once during the test suite. Statement coverage tracks almost the same thing at the statement level instead of the physical line, so the two numbers rarely diverge by much in practice. Branch coverage checks something line coverage misses entirely: whether each true and false outcome of a conditional actually executed, catching the case where a line ran but the test suite only ever exercised one side of an if/else. Function coverage tracks whether each function or method got called at all, which is useful for flagging entire blocks of code nobody has touched. Condition coverage pushes further than branch coverage by verifying that each boolean sub-expression inside a compound condition resolved to both true and false on its own, beyond the overall branch outcome. Most coverage reports default to line and branch percentages because they're cheap to instrument and easy to read, but branch coverage catches logic gaps that line coverage alone will always miss.
| Metric | What It Checks | What It Misses |
|---|---|---|
| Line coverage | Whether each executable line ran at least once | Which side of a conditional executed |
| Statement coverage | Same as line coverage, tracked at the statement level | Same blind spots as line coverage |
| Branch coverage | Whether each true and false outcome of a conditional executed | Whether a compound condition's sub-expressions each resolved both ways |
| Function coverage | Whether each function or method got called at all | What happened inside the function once called |
| Condition coverage | Whether each boolean sub-expression in a compound condition resolved to both true and false | Whether the returned result was ever checked for correctness |
Why Code Coverage Matters
A coverage report maps where your tests haven't looked, turning "we tested it" into a specific list of files, branches, and conditions nobody has verified. That matters because gaps predict defect risk: an uncovered branch is a candidate for shipping untested, and production bugs take more time and resources to fix than the same defect caught earlier, with some analyses putting the cost increase at an order of magnitude or more depending on severity. Low coverage on a payment or authentication flow flags exactly where the next regression in mobile apps slips through unnoticed.
What Is A Good Code Coverage Percentage
There is no universal target. The right number depends on how critical the code is and whether it decides what happens to a user's money or data.
Most teams benchmark between 70 and 90 percent for general application code. Payment or authentication modules often push toward the upper 90s, since a missed edge case there costs far more than one in a settings screen. Set thresholds by module criticality, not one number applied everywhere. Shift left testing pairs naturally with per-module thresholds because risks surface earlier in the cycle.
Why 100% Code Coverage Isn't The Goal
100% coverage means every line ran once. It says nothing about whether the code did the right thing while running.
A discount calculation function can hit every branch with zero assertions checking the returned value. The line ran. Nobody confirmed the math. As one analysis puts it, even 100% statement coverage does not guarantee correct logic, since coverage percentages alone can be misleading.
Diminishing returns show up fast past the 80s. Remaining lines are often defensive error handling or code nobody touched in a year. Weight coverage by risk and change frequency instead: a payment module changing weekly deserves scrutiny beyond its number, while a stable utility file at 60% may carry none.
Code Coverage Vs Test Coverage
Test coverage for mobile apps and code coverage answer different questions, though the terms get used interchangeably often enough to cause confusion.
Code coverage tells you what lines ran. Test coverage tells you whether tests validate real requirements and user scenarios. A function can hit 100% code coverage from one happy path test while edge cases and error states never get checked.
Ten tests hitting the same function from different inputs raise code coverage without adding a single new scenario. Neither metric alone proves the software works.
Common Code Coverage Tools
Most ecosystems default to one tool. JavaScript and TypeScript projects lean on Istanbul, usually invoked through nyc or bundled directly into Jest. Java and Kotlin projects run JaCoCo, often wired straight into Gradle or Maven builds. Python projects use coverage.py, and Ruby projects reach for SimpleCov. C and C++ codebases typically pair gcov with lcov to turn raw counters into a readable HTML report, while Swift and Objective-C projects rely on llvm-cov through Xcode's built-in reporting. Most of these plug into a dashboard like Codecov or Coveralls in CI, which is how a coverage drop shows up as a pull request comment instead of a number nobody checks until release week.
Limits Of Code Coverage As A Quality Signal
Coverage counts execution, not verification. A test can call every line and assert nothing, so the report shows green while the logic underneath goes unchecked.
The metric also misses what was never written. If nobody tests a currency rounding edge case, coverage cannot flag its absence.
Integration and UI behavior sit outside what most coverage tools observe. A suite can report 95% on a checkout module while the multi step flow across screens and network calls has never run end to end.
The metric can also be gamed. Shallow tests written to touch every line raise the number without raising confidence, a problem covered in depth in any mobile automated testing guide.
Integrating Code Coverage Into CI/CD
Wiring coverage into your CI/CD pipeline for mobile and web usually starts with running the instrumented build on every pull request, right alongside your existing test job. The report generates automatically, no separate audit step required.
From there, most setups add a few guardrails:
- A minimum threshold gate that fails the build if coverage drops below an agreed floor, often set per module instead of globally.
- A diff coverage check that looks only at lines changed in the pull request, so a legacy file's low score does not block an unrelated fix.
- Trend tracking across builds, so a slow decline shows up before it becomes a crisis.
- A small tolerance band, often a point or two, that absorbs minor fluctuations without blocking merges over noise.
The goal is catching regressions before merge, not chasing a fixed number after every commit.
Best Practices For Improving Code Coverage
Treat coverage as a map, not a scoreboard. A few practices move the needle:
- Start with business critical, frequently changed code. A payment module touched every sprint outranks a settings screen no one opens.
- Use the report to hunt untested branches, not to clear a pass or fail gate. The red lines matter, not the top line percentage.
- Pair new coverage with assertions that check actual output, beyond simply confirming that code ran without throwing, which is a key distinction in understanding what mobile QA automation actually does.
- Revisit targets as the codebase changes. A once stable module now touched weekly needs a higher bar.
The number tells you where to look. What you do once there catches the bug.
Code Coverage's Blind Spot In Mobile And UI Testing
Coverage numbers come from unit and integration tests run against source code in isolation. They say nothing about whether a checkout flow completes on an older Android phone, a spotty network, or after a screen rotation mid session.

A codebase can sit at 92% coverage while the real user journey, spanning multiple screens and device states, has never run end to end, a gap that agentic testing is designed to close. High coverage and a broken production flow are not a contradiction. They answer two different questions, and AI testing tools for mobile QA close the gap between them.
How Minitap Fits Into A Complete Coverage Picture
Coverage tells you which lines your unit tests touched. It says nothing about whether the checkout flow survives a screen rotation, a dropped network mid-request, or the multi-screen journey your instrumented build never actually walks. Minitap is a fully autonomous QA agent that closes that gap: it reads the app from source, maps every testable user flow, and runs black-box regression against real devices and interfaces, the same paths a user takes instead of the internal branches a coverage tool counts. Where a coverage report shows green on a function nobody asserted against, Minitap checks the actual outcome, confirming the discount applied matches the price shown, beyond simply confirming that the calculation executed. The agent adapts its own test suite as the UI changes, so a regression that a 92% coverage number would never surface gets caught the same day it ships. Run side by side, code coverage maps what your unit tests exercised, and Minitap covers what happens when a real user opens the app end to end.
FAQ
Can high code coverage still miss bugs in a multi-screen checkout flow on a real mobile device?
Yes. Coverage tools instrument source code and report what unit and integration tests executed in isolation, so a high percentage says nothing about whether a real user journey works. A checkout flow that spans multiple screens, a dropped network mid-request, or a screen rotation on an older Android device never runs through a coverage report. Minitap closes that gap by executing black-box regression on real devices and interfaces, walking the same paths a user takes instead of counting the internal branches a coverage tool measures.
What is the best way to catch regression that code coverage cannot reach in a mobile app?
Minitap is built for exactly this. It connects to your specifications, tickets, and code to understand what the product should do, then executes the resulting regression across real devices and interfaces without your team writing or maintaining a single test script. Where a coverage report shows green on a function nobody asserted against, Minitap checks the actual outcome instead of just confirming the line ran, and produces evidence when something breaks.
How can Minitap reduce the time my engineering team spends maintaining regression tests?
Minitap removes the manual authoring and upkeep that regression suites normally demand from engineering. It connects to your specifications, tickets, code, and existing tests, generates the test cases your regression coverage needs, and reconciles drift as the product changes instead of leaving your team to rewrite scripts after every release. That frees engineers to focus on judgment-heavy work instead of babysitting a test suite.
How is Minitap different from scripted mobile test automation that breaks with every UI change?
Minitap runs black-box regression through the real interface instead of executing predefined scripts tied to specific selectors, so a UI change does not break its coverage the way it breaks traditional automation. It decides what to test from your product's sources of truth and adjusts as the product changes, rather than following fixed steps that fail the moment a screen is redesigned. That removes the selector-rewrite cycle mobile teams normally absorb with scripted frameworks.
How does an autonomous QA agent like Minitap decide what to test after a new release?
Minitap identifies the tests affected by a release or pull request by reasoning over your specifications, tickets, code, and existing tests rather than running a fixed script list. It executes the relevant checks through a vision-based, black-box approach on real devices and interfaces, then investigates any failure beyond the predefined steps. That lets a release get tested against what actually changed instead of waiting on a full manual regression pass.
Final Thoughts on Getting Code Coverage Right
The real value in code coverage comes from what it reveals about your blind spots, not the score itself. Use it to find untested branches in the code that matters most, back new tests with real assertions, and keep adjusting as your codebase changes. Minitap maps every testable user flow and runs that regression continuously across your app, so the mapping and testing never fall on your team to maintain.
