By NHI Mgmt Group Editorial TeamDomain: Cyber SecuritySource: SonarPublished May 4, 2026

TL;DR: Most 0% coverage results come from handoff failures such as missing reports, wrong formats, deprecated properties, or CI timing, according to Sonar. The broader lesson is that coverage is a pipeline integrity problem, and AI-generated tests can still pass while verifying nothing.


At a glance

What this is: This is Sonar’s analysis of why SonarQube coverage often shows 0% or mismatched numbers, with the key finding that the failure usually sits in the test-to-report-to-scanner pipeline rather than in SonarQube itself.

Why it matters: For IAM and security practitioners running software delivery platforms, the pattern matters because incomplete or misleading telemetry creates false confidence in controls, and the same governance discipline used for identity pipelines applies to build-time quality signals.

👉 Read Sonar's explanation of why SonarQube coverage reports fail


Context

Code coverage in SonarQube is a data-integration problem before it is a quality metric problem. The platform imports reports from tools such as JaCoCo, coverage.py, Istanbul, and similar language-specific instruments, so a missing report, wrong format, or stale property can make a healthy test suite look like it has no coverage at all. The issue is common in CI pipelines because each handoff introduces a separate failure point.

The security governance parallel is straightforward: if the pipeline that produces assurance data is brittle, teams can mistake absence of evidence for evidence of failure, or the reverse. That matters wherever identity, secrets, or build controls depend on accurate analysis of automated outputs, because compromised or misconfigured pipelines can hide real gaps just as easily as they can create false alarms.


Key questions

Q: How should teams troubleshoot 0% code coverage in SonarQube?

A: Start at the pipeline, not the dashboard. Confirm that tests executed, a coverage report was generated, the report uses the expected format, the scanner property points to the right path, and the scanner runs after the report exists. If all of that is true, inspect debug logs for unresolved paths or ignored reports.

Q: Why do SonarQube coverage numbers differ from pytest or JaCoCo?

A: They often count different things. Python tools may count imports and function definitions, while SonarQube counts executable logic only. JaCoCo may include closing braces in its denominator, and SonarQube combines line and branch coverage. The gap is usually a measurement model difference, not a defect in either tool.

Q: What do security teams get wrong about coverage as a control signal?

A: They treat coverage as proof that code is well tested. In reality, coverage only shows that code ran during tests. A test can produce high coverage while asserting nothing meaningful, so organisations need test-quality checks as well as coverage targets.

Q: How do you know when coverage failures are caused by CI configuration?

A: When the tests pass but the report is missing, the report is in the wrong format, or the scanner runs before the report is created, the issue is almost certainly CI configuration. That is where teams should look first, especially in containerised builds and parallel jobs.


Technical breakdown

Why SonarQube shows 0% coverage even when tests pass

SonarQube coverage depends on four stages: tests execute, a coverage tool records execution, the tool writes a report, and the scanner imports that report. A failure at any stage produces the same dashboard symptom. Automatic analysis in SonarQube Cloud cannot import coverage reports, deprecated scanner property names are ignored silently, and path mismatches make valid reports unreadable. The result is a pipeline integrity problem, not a single-tool defect.

Practical implication: verify each handoff independently before changing test code or assuming the platform is broken.

Why coverage tools and SonarQube count different lines

Coverage tools do not all define a coverable line the same way. Python coverage tools often count imports, class declarations, and function definitions, while SonarQube counts executable logic only. JaCoCo can count closing braces that SonarQube ignores, and SonarQube also combines line and branch coverage into a single metric. That means two tools can describe the same codebase honestly while still producing different percentages.

Practical implication: compare like with like by understanding whether a gap is caused by denominator differences or a genuine test gap.

Why tests with high coverage can still miss defects

Coverage measures execution, not verification. A test can call a function, achieve full line coverage, and still assert nothing about the result. SonarQube’s rules such as java:S2699, python:S5915, and java:S2187 target that weakness by detecting tests without assertions, assertions that never run, and empty test classes. This is where metric-driven quality checks and behavioural verification diverge.

Practical implication: pair coverage thresholds with test-quality rules so that executed code is also meaningfully checked.


NHI Mgmt Group analysis

Coverage integrity is a governance problem, not just a developer inconvenience. The article shows that a passing test suite can still produce 0% or misleadingly low coverage if the report handoff fails. That is the same control pattern identity teams see when telemetry is present but not trustworthy. The practitioner lesson is to treat build-time assurance data as a governed control surface, not a side effect of tooling.

Silent failure modes are the real risk in coverage pipelines. Deprecated property names, wrong report paths, and unsupported analysis modes fail without obvious errors, which means teams can ship false confidence at scale. In governance terms, this is a visibility gap created by weak validation at the scanner boundary. The practitioner conclusion is that silent ignore paths deserve the same scrutiny as outright build failures.

Metric differences must be interpreted, not disputed. Python, Java, and JavaScript tools count executable coverage differently, so SonarQube may report lower numbers without being wrong. That distinction matters for any programme that uses coverage as a quality gate, because the wrong comparison can drive misplaced remediation work. The practitioner takeaway is to standardise metric interpretation before enforcing targets.

AI-generated tests create a new assurance debt. The article’s warning about tests that execute code but assert nothing becomes more important as AI tooling writes more boilerplate tests. Coverage can rise while behavioural verification falls behind, which means teams can optimise the wrong signal. The practitioner conclusion is to govern test quality, not just test volume.

What this signals

Build assurance now behaves like any other control plane: if the data feed is brittle, the metric becomes a narrative rather than evidence. Teams that rely on SonarQube for quality gates should expect the same discipline they apply to IAM telemetry, meaning explicit validation of inputs, paths, and failure states before trusting the output.

Coverage signal drift: different tools can report different percentages for the same codebase because they define coverable lines differently. That is not a tooling dispute so much as a governance issue, and programmes that do not standardise how they interpret coverage will make inconsistent release decisions. The safer path is to align metric semantics before enforcing thresholds.


For practitioners

  • Validate the coverage handoff chain Check that tests run, a coverage report is written, the report format matches the language, and the scanner points to the correct file before you inspect the dashboard.
  • Remove silent failure paths Audit scanner properties for deprecated names, confirm the analysis mode supports coverage import, and fail the pipeline when the report file is missing or unreadable.
  • Standardise path handling in CI Use relative file paths that match the scanner’s project view, and fix monorepo or container path mismatches with language-specific settings such as relative_files where appropriate.
  • Separate coverage from verification Keep coverage thresholds, but add rules that catch tests with no assertions, unreachable assertions, and empty test classes so that execution does not masquerade as quality.

Key takeaways

  • Coverage problems usually begin at the report handoff, not in SonarQube itself.
  • A higher coverage percentage does not guarantee better tests if the assertions are weak or absent.
  • Teams should govern coverage pipelines as assurance controls, with validation for formats, paths, timing, and test quality.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

NIST CSF 2.0, NIST SP 800-53 Rev 5 and CIS Controls v8 set the technical controls, while ISO/IEC 27001:2022 define the regulatory obligations.

FrameworkControl / ReferenceRelevance
NIST CSF 2.0DE.CM-1Coverage pipelines are monitoring telemetry that must be trustworthy and validated.
NIST SP 800-53 Rev 5SI-4Scanner and report validation supports system monitoring for build integrity failures.
CIS Controls v8CIS-8 , Audit Log ManagementScanner debug logs provide the audit trail for coverage import failures.
ISO/IEC 27001:2022A.8.25Secure development lifecycle controls apply to build and test assurance flows.

Validate coverage imports as a monitored control signal and alert on missing or malformed reports.


Key terms

  • Coverage report: A coverage report is the file produced by a testing tool that records which lines or branches executed during automated tests. SonarQube does not create this data itself. It imports the report and computes its own metric from the file it receives.
  • Scanner property: A scanner property is a configuration key that tells SonarQube where to find an analysis input such as a coverage report. If the property name is deprecated, misspelled, or points to the wrong path, SonarQube may silently ignore the data and report 0% coverage.
  • Executable line: An executable line is code that a platform considers capable of being run and therefore counted in coverage calculations. Different tools define this differently, which is why SonarQube can show a lower or higher percentage than a language-specific coverage tool on the same codebase.

What's in the full article

Sonar's full article covers the operational debugging detail this post intentionally leaves at a higher level:

  • Language-specific report paths and file locations for Java, JavaScript, Python, C#, and Go builds
  • Exact scanner property names that replace deprecated settings and prevent silent import failures
  • Debug-log checks that show whether the report was found, parsed, or skipped during analysis
  • CI ordering examples that show how to ensure the scanner runs only after coverage output exists

👉 The full Sonar article breaks down the report formats, scanner properties, and CI handoff checks in detail.

Deepen your knowledge

NHI Foundation Level course, the industry's only accredited NHI security programme, covers NHI governance, machine identity security, secrets management, and identity lifecycle control. It is designed for practitioners who need stronger governance across identity, automation, and security operations.
NHIMG Editorial Note
Published by the NHIMG editorial team on August 19, 2026.
NHI Mgmt Group — the independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org