A snapshot of how much of the codebase or feature set is covered by automated tests.
A test coverage report measures how much of a codebase the test suiteTest SuiteQuality AssuranceA suite of related testsView reference → actually exercises, broken down by lines, branches, and statements. It answers a narrow, useful question: which code ran when the tests ran? The trouble starts when teams read the percentage as a grade for test quality, which it is not. High coverage means the tests touched the code, not that they checked anything worth checking.
Coverage measurement is old. Statement, branch, and path coverage were formalised in software-testing literature through the 1960s and 70s, and the distinctions still hold: line coverage reports which lines executed, branch coverage reports which decisionDecisionStrategyA recorded decision with context, rationale, and consequencesView reference → outcomesOutcomeStrategyA desired business or user outcomeView reference → (the true and false sides of each if) executed, and branch coverage is the stricter bar because a single line can hide an untested path.
The instructive evolution is the critique. Martin Fowler argues that test coverage is a useful tool for finding untested parts of a codebase and of little use as a numeric statement of how good the tests are. He warns that he would be suspicious of anything near 100%, because it smells of tests written to satisfy the number rather than to think about behaviour. This is Goodhart's Law applied to engineering: make coverage a target and people reach it cheaply, writing tests that execute code without asserting anything about it. The field has largely landed on Fowler's reading. Coverage is a gap-finder, read in the gaps rather than the headline figure.
A service reports 92% line coverage and the team treats it as healthy. A closer read of the report tells a different story. The uncovered 8% is concentrated in the payment-retry and error-handling paths, the exact code most expensive to get wrong, while the well-covered 92% is mostly getters and serialisation. Branch coverage, lower at 71%, reveals that several if statements have only their happy path tested. The team stops chasing the top-line number and uses the report as a map: it writes tests for the retry logic and the untested error branches, accepting that the line percentage barely moves. Three months later a production incidentIncidentDevOps & PlatformA production incidentView reference → traces to exactly the kind of error branch they had filled in, and the test catches the regression. The report did its jobJobUserJob To Be Done: what the user is trying to accomplishView reference → by showing where the tests were not, not by being high.
In the Unified Product Graph, a test coverage report sits in the testing region as a measurement node. It attaches to what it measures through Productmeasured byTest Coverage Reporthierarchy and product_measured_by_test_coverage_reportTest Suitemeasured byTest Coverage Reporthierarchy, and it points at the code it covers through test_suite_measured_by_test_coverage_reportTest Coverage ReportcoversServicecross-domain. Keeping the report distinct from the test_coverage_report_covers_serviceTest SuiteQuality AssuranceA suite of related testsView reference → records coverage as an observationObservationUser ResearchA specific behaviour or statement observedView reference → with a target, so a team can track whether a service's coverage is rising or quietly eroding as the codebase grows. Tying it to test_suiteServiceEngineeringA deployable service or microserviceView reference → rather than to the product as a whole keeps the measurement honest at the level where untested riskRiskComplianceA risk to the product or businessView reference → actually lives.service
Type-specific fields on BaseNode
line_coveragenumberPercentage of lines covered (0-100)
branch_coveragenumberPercentage of branches covered (0-100)
function_coveragenumberPercentage of functions covered (0-100)
statement_coveragenumberPercentage of statements covered (0-100)
target_coveragenumberCoverage target threshold set by the team (0-100)
uncovered_linesnumberNumber of lines not covered by any test
report_datestringISO date when the report was generated
idstringrequiredUnique identifier (UUID)
typeNodeTyperequiredDiscriminator for the entity type
titlestringrequiredDisplay name
descriptionstringOptional detailed description
statusstringLifecycle status
tagsstring[]Freeform tags for filtering
3 edge types connected to this entity.
product_measured_by_test_coverage_reporttest_suite_measured_by_test_coverage_reporttest_coverage_report_covers_service