Join us at Qt C++ Warsaw Meetup - 21.08.2025

Sign up for free!

Code Coverage vs. Test Coverage: Metrics That Matter for Compliance and Quality

Software development
2025-08-06
17 minutes
Code Coverage vs. Test Coverage

Ensuring high quality and regulatory compliance in quality industries requires rigorous software testing and validation. Among the key metrics used to assess testing effectiveness are code coverage and test coverage. While closely related, these terms have distinct meanings and implications.

That’s why understanding the difference between them is essential for building safe, certifiable products.

If you’re developing medical software or safety-critical systems—and need clarity on how to measure, improve, and communicate test effectiveness—this article is for you.

We’ll cover:

 

  • defines each term, explores their differences with practical examples
  • highlights relevant tools
  • explains their importance for product quality, test strategy, and regulatory compliance
  • Finally, we offer guidance for CTOs and managers on interpreting and acting on these metrics to ensure both robust software and regulatory approval

Need help aligning your testing practices with compliance requirements or scaling your test strategy effectively?
Let’s talk about how we can support your team with the right tools, insights, and expertise.

 

What Is Code Coverage?

Code coverage is a quantitative measure of how much of your application’s source code is executed when running tests. In simple terms, it tells you which lines, functions, or branches of code have been run by your test suite, and which have not. Code coverage is typically expressed as a percentage (e.g. “75% of lines executed”). Higher percentages mean fewer parts of the code are left untested by any automated tests.

 

How It’s Measure?

Code coverage is measured through instrumentation or analysis tools that monitor which code runs during the testing process. Common coverage criteria include:

 

  • Line/Statement Coverage: The percentage of lines or statements executed at least once.
  •  

  • Branch (Decision) Coverage: The percentage of decision branches (e.g. the true and false paths of each if/else or loop) executed by tests. 100% branch coverage implies every decision outcome has been tested at least once.
  •  

  • Function Coverage: How many of the defined functions (or methods) have been called by tests.
  •  

  • Condition Coverage (MC/DC): Whether each boolean sub-expression was tested for both true and false outcomes (a criterion often required in high-criticality systems).
  •  

  • Path Coverage: Ensures all possible execution paths through the code have been tested (this can be very exhaustive).

 
Types of Code Coverage Metrics
 

Example

Consider a simple function with an if-else clause handling a medical sensor reading. If your tests only exercise the “if” branch and never trigger the “else” branch, you might have 100% line coverage (all lines ran) but only 50% branch coverage (one of two branches executed). A code coverage report would flag that the else-path wasn’t tested. By adding a test to cover the else condition, you’d increase branch coverage to 100%. This way, code coverage metrics help identify untested areas of the codebase.

 

Why Code Coverage Matters?

In safety-critical software, untested code is a liability. High code coverage gives confidence that most of the code has been evaluated under test conditions, which in turn lowers the chance of undiscovered bugs in production. Specifically, code coverage can:

 

  • Expose Dead or Untested Code: It shines a spotlight on code segments not touched by any test, allowing removal of dead code and prompting new tests where needed.
  •  

  • Improve Software Reliability: Focusing tests to cover critical code paths shortens development cycles and enhances reliability.
  •  

  • Quantitatively Assess Test Rigor: It provides a numeric gauge of test thoroughness—code coverage measures like line and branch metrics help teams quantify testing completeness. Setting a minimum coverage threshold (e.g. “no release with <80% coverage”) is common to prevent regression in test diligence.
  •  

  • Support Compliance Evidence: Coverage reports serve as evidence that you’ve exercised the code, which is valuable in audits or certification processes in regulated domains.

 

Limitations

While code coverage verifies that code was executed, it doesn’t confirm correct behavior or that outputs were validated. It’s possible to have 90%+ coverage and still miss critical bugs if the tests are not asserting correct behavior or if the 10% untested code contains the edge cases. Also, achieving very high coverage (close to 100%) can lead to diminishing returns – tests written purely to hit every line can be trivial and not catch meaningful issues. Thus, 100% code coverage does not guarantee bug-free software or adequate testing. It simply indicates that tests executed every line/branch; the onus is on the team to ensure those tests actually verify correct outcomes.

 

What Is Test Coverage?

Broadly, test coverage refers to the extent your tests align with requirements, features, and risk-based needs—not just code paths. Instead of looking at code execution, test coverage asks: have we written tests for every important user scenario, business requirement, or risk identified in the specs? It’s about mapping tests to the intended functionality and ensuring nothing important was left untested from a behavior perspective.

 

How It’s Assessed?

Unlike code coverage, test coverage isn’t a single percentage metric automatically calculated by a tool. It often involves creating a traceability matrix or listing requirements vs. test cases. For example:

 

  • Requirements Coverage: Every software requirement (e.g. “System shall calculate insulin dose within 5% accuracy”) should have one or more tests verifying it. If 45 of 50 requirements have at least one passing test, your requirements test coverage is 90%. Gaps highlight unverified functionality.
  •  

  • Feature/Scenario Coverage: All high-level use cases or user stories (normal and edge cases) are tested. In a medical app, scenarios might include valid inputs, invalid inputs, error handling, integration with hardware, etc. Test coverage ensures each is addressed.
  •  

  • Risk Coverage: For safety-critical devices, risk management (e.g. per ISO 14971) identifies hazardous scenarios. Test coverage means testing mitigations for each identified hazard. For instance, if one risk is “dose calculation overflow”, there should be a test for that condition.

 

Why Test Coverage Matters?

High test coverage ensures the system behaves correctly across conditions and validates outcomes through successful test execution. It helps ensure the software does what it’s supposed to do (and handles what it shouldn’t do), reducing the chance that any specified functionality slips through untested. Key benefits include:

 

  • Validation of All Functional Requirements: High test coverage means you’ve validated each intended function of the software against its acceptance criteria. This is crucial in medicine: missing a test for a requirement could mean missing a critical defect.
  •  

  • Risk Reduction: By covering scenarios and edge cases (including failure modes), you catch issues that could lead to safety risks. This is a strong indicator of robust quality assurance from a user’s perspective.
  •  

  • Confidence for Stakeholders: Non-technical stakeholders (QA managers, regulatory bodies) often care that all use cases are tested. It boosts confidence to report, for example, that “100% of critical use scenarios and 95% of overall requirements are tested,” indicating thorough validation.
  •  

  • Guidance for Testing Effort: Test coverage analysis can reveal untested areas of functionality, guiding where to design new tests. Unlike code coverage which finds code gaps, this finds behavior gaps – for instance, “we have no test for what happens if the network fails during data upload.”

 

Limitations

Test coverage, being qualitative, can be harder to measure objectively. It’s only as good as the requirements and test design – if a requirement was missed or mis-specified, 100% test coverage of known requirements may still miss a critical behavior. Also, like code coverage, high test coverage doesn’t guarantee that the tests are effective; poor test cases can give a false sense of security. Finally, ensuring traceability for full test coverage can be resource-intensive, depending on the rigor required (in regulated contexts, this often involves significant documentation). This is especially true when relying on manual testing, where human factors can lead to inconsistencies in test execution or documentation.

 

How Do They Differ? – Code Coverage vs. Test Coverage Comparison

Both metrics aim to improve software quality but from different angles. They are complementary: code coverage asks “which parts of our code did we execute in tests?” and test coverage asks “which parts of our plan/requirements did we verify with tests?”. Here is a comparison:

Aspect Code Coverage Test Coverage
Definition Percentage of source code executed during testing.

“How much of the code have we run in tests?”

>Extent to which the software’s requirements, features, and risks are covered by tests.

“How much of the functionality have we tested?”

Perspective White-box: Focuses on internal code structure (lines, branches, etc.) >Black-box: Focuses on externally visible behavior and requirements. Viewed from software testing and end-user perspective.
Measured By Quantitative metrics (%, counts of lines/branches executed) from instrumentation tools. Qualitative mapping of tests to requirements or scenarios (often via manual analysis or test management tools). Result is “X of Y requirements covered”.
Common Tools Code coverage tools (e.g. Coco for C++/Qt, JaCoCo for Java, Istanbul/nyc for JavaScript, Coverage.py for Python) instrument code to log executed parts. Test case management and requirements traceability tools (e.g. test management systems, trace matrices). Also leveraging automation frameworks (JUnit, Selenium, etc.) to ensure each requirement has tests.
Typical Owners Developers, especially during unit testing, to ensure all code paths are tested. Often integrated in CI pipelines. QA engineers and test managers, during integration/system testing, ensuring all features & requirements have test coverage. Also reviewed by compliance officers for traceability.
Output & Gaps Yields coverage reports highlighting unexecuted code (e.g. “lines 40-50 not covered”). Gaps point to code that lacks tests (potential blind spots or dead code) Yields matrices or lists of untested requirements/scenarios (e.g. “No test for requirement 3.1 – error handling of invalid input”). Gaps point to functionality not validated by any test (potential unmet spec or unverified risk).
Value >Improves test depth: ensures tests exercise the internals, finding bugs in untested code sections. Essential for refactoring confidence and preventing regressions in code logic. Improves test breadth: ensures the test suite covers all intended behaviors, catching missing test cases for certain features. Essential for confirming the product meets all requirements and user needs.
Limitations Doesn’t assess what is asserted – 100% code coverage can’t ensure the tests checked correct outcomes or that requirements are met. Can be gamed by writing trivial tests or by excluding code from analysis. Harder to quantify – “100% test coverage” is only as complete as your requirement list. Doesn’t directly show how thoroughly code is exercised (a test might tick off a requirement but only cover one code path). Relies on good specification of requirements.

 

Code Coverage Tool

To effectively track coverage, various tools are available. Here are some notable ones and how they support your coverage goals:

 

Coco (for Qt/C++ and more)

Coco is a comprehensive code coverage analysis tool by Qt Quality Assurance, supporting C, C++, C#, QML, and other languages. It instruments your program and can report multiple coverage levels (statement, branch, MC/DC, etc.) Coco is well-suited for embedded development and Qt framework; it not only measures coverage but also helps optimize testing by finding untested or redundantly tested code and even identifying dead code. In a medical project using Qt or C++, Coco can be invaluable for demonstrating thorough testing to auditors, with support for merging results from multiple test runs and generating detailed HTML/JSON reports. (Coco is a commercial tool, but its rich feature set is designed to meet high standards like IEC 62304 compliance).

 

LCOV (C/C++)

LCOV is a widely used open-source coverage tool for C and C++ development built on top of GCC’s gcov utility. It collects coverage data from instrumented binaries and generates detailed HTML reports that include line and branch coverage. LCOV integrates well with Unix/Linux-based build environments (like Make or CMake) and is especially common in CI pipelines where code quality gates are enforced. For example, in a safety-critical embedded application, LCOV can help show auditors that critical conditions and paths are tested by visualizing which lines and branches remain uncovered. While it lacks some advanced analytics of commercial tools, its lightweight nature and strong community support make it a reliable choice for many regulated industries, including automotive and medical.

 
Tools for Code & Test Coverage
 

OpenCppCoverage (Windows/C++)

OpenCppCoverage is a free, Windows-based code coverage tool for C++ applications, using Microsoft’s Visual C++ compiler (MSVC). It instruments the code at runtime to report line and function coverage, making it especially suitable for native Windows development environments. The tool outputs human-readable reports (HTML, XML) and can filter files and symbols to focus on specific modules or libraries. In a Windows-based medical desktop application, OpenCppCoverage could help identify untested logic in a device calibration module. Although simpler than tools like Coco, it’s valuable in constrained setups where Visual Studio is the primary environment and commercial tools are not an option.

 

Coverage.py (Python)

Coverage.py is the standard tool for measuring code coverage in Python programs. It uses Python’s tracing hooks to record which lines of code execute during tests. After running your test suite (e.g., with pytest), Coverage.py can generate a report (text or HTML) showing which lines were executed and which missed. In a Python-based medical data analysis tool, for example, Coverage.py might reveal that a data parsing module wasn’t exercised by tests – prompting the team to add needed tests. It supports branch coverage as well, and is easily integrated via plugins like pytest-cov.

 

Other Tools

Many other coverage tools exist for various languages (e.g., Cobertura or OpenClover for Java, dotCover for .NET, gcov for C, etc.), but the concept remains the same – they help ensure no part of the critical code is left untested. It’s also worth noting that test management tools (for test coverage) such as Jama, Polarion, or Helix ALM can track requirement-to-test traceability, which is how test coverage is often managed in regulated industries.

Practical Tip

In continuous integration (CI), you can automate these tools to get coverage results on each build. For example, a CI pipeline might run unit tests with Coco or JaCoCo and then fail or warn if coverage decreased. This keeps the team informed and accountable for coverage metrics over the project’s life. The Coco tool even offers a Test Data Generator and optimization suggestions to help reach higher coverage faster – useful when striving to meet stringent quality goals.

 

Coverage in Safety-Critical Domains (Medical Software)

In medical device software testing, regulatory standards and guidelines place heavy emphasis on thorough testing – both in terms of meeting requirements and exercising the code. While IEC 62304 (the international standard for medical device software lifecycle) does not mandate a specific numeric coverage level, it “indicates the need for rigorous testing, acceptance criteria, and traceability”, which implicitly calls for using coverage analysis and other tools to ensure software safety. Here’s how coverage metrics tie into quality and compliance:

 

Regulatory Expectations

For Class C medical software (where software failure could cause serious injury or death), regulators expect evidence that the software is extensively verified. The FDA’s guidance, for example, explicitly mentions testing coverage as a means to build confidence in software safety before release. One FDA guidance statement notes that decision coverage (branch coverage) “is considered to be a minimum level of coverage for most software products, but decision coverage alone is insufficient for high-integrity applications.”

In practice, this means an FDA reviewer will be happier if you show not just 100% branch coverage, but also that critical algorithms meet more stringent criteria (like MC/DC coverage) for the highest risk software. High code coverage thus becomes a de facto requirement in safety-critical systems – many organizations developing Class C devices aim for 100% code coverage (at least for lines and branches) to satisfy internal quality goals and provide assurance to auditors.

 
V&V Lifecycle in Software Development
 

Quality Risk Management

Medical software development includes identifying hazards and mitigations. Test coverage is tied to this via requirements-based testing and risk-based testing (both mentioned in IEC 62304). You need to demonstrate that all risk control measures in the software have been tested. For instance, if a requirement says “Software shall issue an alert on communication failure with pump”, you must have a test for that scenario. Traceability matrices link each such requirement to one or more test cases, showing regulators that every identified risk and requirement has at least one passing test. This is essentially test coverage of requirements, and it’s often reviewed during certification audits.

 

Product Quality and Reliability

From an engineering standpoint, high coverage metrics directly contribute to product quality. In life-critical applications, untested code is too risky to leave in the product. By using code coverage tools, teams often discover parts of the code that were not executed by any test – for example, an error-handling branch that triggers only on a rare sensor fault. Knowing this, they can write a new test (or simulate the fault) to cover that branch, potentially uncovering a bug that would only show up in the field. In other words, coverage metrics help catch latent bugs before the product is deployed to hospitals or patients. The end result is a more robust product with fewer post-release failures.

 

Continuous Improvement and Test Strategy

Coverage trends over time are also important—they help ensure new features are accompanied by tests and that tests cover evolving risk areas. For example, if the infusion pump dosage calculation module is only 60% covered by tests but is safety-critical, managers should allocate more testing resources there. Conversely, if a less critical module is at 95% coverage, effort might be rebalanced. Coverage trends over time are also important – if coverage drops, it may indicate new code was added without tests (a process lapse that needs correction). Many safety-focused teams make coverage a key quality KPI and review it regularly in project meetings.

 

Compliance Documentation

When seeking certification (FDA 510(k), CE marking under MDR, etc.), development teams often include coverage analysis reports in the submission or technical file. These documents demonstrate due diligence. For instance, an IEC 62304 Class C project might include a summary that “Unit testing achieved 98% statement and 100% branch coverage for all Class C modules,” backed by tool reports. Additionally, tool qualification can come into play: if you use a coverage tool to meet a regulatory requirement, standards like IEC 62304 and ISO 13485 require that tool to be validated/qualified for use. (Many vendors, including Qt for Coco, provide Tool Qualification Kits to facilitate this)

 

Interpreting Coverage Metrics – Guidance for Executives and Managers

It’s easy for teams to treat coverage numbers as a checkbox or vanity metric. However, used wisely, they are powerful tools for managing software quality. Here are some tips for CTOs, QA managers, and other executives on making the most of code and test coverage data:

 

  • Look Beyond the Number: A high percentage is good, but always ask “coverage of what?” Ensure that code coverage includes the most critical components of your system (those related to patient safety).
  •  

  • Integrate with Risk Management: Tie coverage goals to risk levels. For example, you might set a policy that all safety-critical modules (Class C in IEC 62304) must hit, say, 95% coverage, whereas less critical modules (Class B/A) might have a slightly lower target.
  •  

  • Use Both Metrics Together: Don’t choose between code vs test coverage – use both.
  •  

  • Set Realistic Coverage Goals: While it might be tempting to mandate 100% code coverage across the board, that can encourage diminishing returns or gaming the system. Industry wisdom often considers ~80% a good baseline for code coverage in general software, but in medical, you likely want higher for critical parts.
  •  

  • Beware of False Security: As mentioned earlier, neither 100% code nor test coverage guarantees defect-free software. Encourage a culture where developers write tests to find bugs, not just to satisfy metrics.
  •  

  • Leverage Coverage in CI & Reporting: Make coverage a routine part of development. Dashboards can show current coverage vs target, and trends over time.
  •  

  • Invest in Tooling and Training: Using tools like Coco, JaCoCo, etc., requires integration and sometimes training.
  •  

  • Prepare for Audits: When going for certifications, be ready to present coverage metrics as evidence of thorough testing.

 

Conclusion

In the context of Safety-Critical Domains, where failures can cost lives, both code coverage and test coverage are indispensable metrics for ensuring software quality and meeting regulatory demands.

Maintaining a balance – quantitative code coverage to ensure no code is left in the dark, and qualitative test coverage to ensure no requirement is left unverified – will put your organization on a strong footing to deliver high-quality, compliant software. By understanding and acting on these metrics judiciously, executives and managers can steer projects to success where it counts the most.

Building safety-critical software comes with high stakes and high expectations.
Whether you need to improve traceability, streamline development, or meet regulatory requirements with confidence — we’re here to help. Let’s talk about how we can support your team across the entire development lifecycle.

Scythe-Studio - Head of Delivery

Michał Woźniak Head of Delivery

Need Qt QML development services?

service partner

Let's face it? It is a challenge to get top Qt QML developers on board. Help yourself and start the collaboration with Somco Software - real experts in Qt C++ framework.

Discover our capabilities

Latest posts

[ 94 ]