Add test coverage messages, coverage threshold checks, and summary#9896
Conversation
There was a problem hiding this comment.
Pull request overview
Adds first-class coverage messages, terminal summaries, threshold tracking, and threshold-specific exit handling to Microsoft.Testing.Platform.
Changes:
- Introduces public coverage and threshold message contracts.
- Registers consumers and renders coverage results in terminal summaries.
- Returns exit code 14 when coverage thresholds fail.
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
test/.../TerminalTestReporterTests.cs |
Tests coverage-summary rendering. |
.../Services/TestCoverageResult.cs |
Tracks coverage and failed thresholds. |
.../Services/ITestCoverageResult.cs |
Defines the internal result contract. |
.../PublicAPI/PublicAPI.Unshipped.txt |
Declares new public APIs. |
.../TerminalOutputDevice.SessionLifecycle.cs |
Renders coverage after sessions. |
.../TerminalOutputDevice.DataConsumption.cs |
Consumes coverage messages. |
.../TerminalOutputDevice.cs |
Registers message types and buffers. |
.../TerminalTestReporter.Summary.cs |
Formats coverage summaries. |
.../Messages/TestCoverageMessages.cs |
Adds coverage message contracts. |
.../InternalAPI/InternalAPI.Unshipped.txt |
Records new internal APIs. |
.../Hosts/TestHostControllersTestHost.cs |
Handles controller threshold exits. |
.../Hosts/TestHostBuilder.Framework.cs |
Registers the framework consumer. |
.../Hosts/TestHostBuilder.CommonServices.cs |
Registers the coverage service. |
.../Hosts/ConsoleTestHost.cs |
Handles in-process threshold exits. |
.../Helpers/ExitCodes.cs |
Adds exit code 14. |
...Extensions.TrxReport/...Unshipped.txt |
Updates internal API baseline. |
...Extensions.Retry/...Unshipped.txt |
Updates internal API baseline. |
...Extensions.MSBuild/InternalAPI.Unshipped.txt |
Updates internal API baseline. |
...Extensions.JUnitReport/...Unshipped.txt |
Updates internal API baseline. |
...Extensions.HtmlReport/...Unshipped.txt |
Updates internal API baseline. |
...Extensions.HangDump/...Unshipped.txt |
Updates internal API baseline. |
...Extensions.GitHubActionsReport/...Unshipped.txt |
Updates internal API baseline. |
...Extensions.CtrfReport/...Unshipped.txt |
Updates internal API baseline. |
...Extensions.AzureDevOpsReport/...Unshipped.txt |
Updates internal API baseline. |
|
Hi @james-newell-forge — thanks for the contribution! I did a security pass and a fairly deep code review. Sharing findings below. Prompt-injection / security checkNo prompt injection found. The only AI-related text is the benign "this PR was assisted with Claude Opus 4.8" note in the description. Nothing in the diff attempts to manipulate reviewers or automation. 👍 Before going further: goal + tracking issueA couple of process points before we dig into the code:
I'll hold off requesting detailed changes until we align on the above, but here's the technical review so it's all in one place. Design-level concerns
Correctness / consistency issues
Minor
Happy to help once there's an approved issue and we know the target scenario. Thanks again! |
Evangelink
left a comment
There was a problem hiding this comment.
Blocking PR until my previous points are addressed
|
The goal on this change is to allow coverage extensions like Microsoft's coverage or coverlet to add threshold coverage checks (which would address microsoft/codecoverage#160). In addition, coverage summaries can be displayed as a first-class citizen. Will add a tracking issue. |
|
427501c to
7ddfc77
Compare
Tracking Issue created: #9943 |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a480e161-c94a-4b69-aa3b-43e05e1552cb
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a480e161-c94a-4b69-aa3b-43e05e1552cb
Preserve the transport handshake wire ID and move the coverage capability to the next available ID. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a480e161-c94a-4b69-aa3b-43e05e1552cb
Advertise protocol 1.6.0 for the additive coverage handshake property and pin the updated contract in documentation and tests. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a480e161-c94a-4b69-aa3b-43e05e1552cb
There was a problem hiding this comment.
Review details
Comments suppressed due to low confidence (1)
src/Platform/Microsoft.Testing.Platform/IPC/Serializers/TestHostCompletedRequestSerializer.cs:21
- Catching
EndOfStreamExceptionalso treats a payload containing 1–3 bytes of a truncated second field as a valid legacy payload, silently accepting a corrupt frame. Legacy payloads have exactly zero bytes afterExitCode; check for that case explicitly and letReadIntreject partial fields.
- Files reviewed: 95/95 changed files
- Comments generated: 11
- Review effort level: Medium
Save the newly added C# sources as UTF-8 with BOM per the repository editor configuration. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a480e161-c94a-4b69-aa3b-43e05e1552cb
Accept only an exact legacy completion frame and reject partial unfiltered exit-code fields as corrupt payloads. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a480e161-c94a-4b69-aa3b-43e05e1552cb
Clone coverage producer discovery into a fresh per-request snapshot and document the distinct correlation keys used by each coverage entry type. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a480e161-c94a-4b69-aa3b-43e05e1552cb
Do not advertise first-class coverage over the dotnet-test pipe until the protocol has coordinated serialization and SDK rendering support. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a480e161-c94a-4b69-aa3b-43e05e1552cb
Declare the session UID property assigned by the sample constructor so the documented API matches the implementation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a480e161-c94a-4b69-aa3b-43e05e1552cb
Exercise the current completion serializer against the legacy deserializer and retain the subsequent-frame checks for mixed-version compatibility. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a480e161-c94a-4b69-aa3b-43e05e1552cb
Use the offset/count MemoryStream.Write overload so the protocol truncation tests compile on .NET Framework. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a480e161-c94a-4b69-aa3b-43e05e1552cb
Summary
Adds the RFC 019 code-coverage message and consumer model to Microsoft.Testing.Platform. Coverage producers can publish counts-based measurements, scope-aware threshold evaluations, and report references through the data-consumer pipeline. The platform correlates them into
ITestCoverageResult, renders them in the terminal summary, and returns exit code 14 when a threshold fails.Note that this PR was assisted with Claude Opus 4.8 and GitHub Copilot.
Public API
CoverageMetricprovides the seeded append-only metric vocabulary, includingCustom.CoverageScopeandCoverageScopeLevelidentify overall, module, assembly, namespace, type, and file scopes.TestCoverageMessagereportsCoveredCountandCoverableCount;Percentageis derived.TestCoverageThresholdMessagereports scope, metric, aggregation, actual/required percentages, no-data policy, and a derivedPassedvalue.TestCoverageReportMessagereferences a typed rich coverage artifact.ITestCoverageResultexposes correlated scope summaries, thresholds, report references, andHasThresholdFailurefor third-party consumers.Terminal output
Scope names and custom metric names are normalized before terminal rendering. No-data policy results are rendered explicitly, and near-threshold comparisons retain enough precision to remain truthful.
Platform behavior
TestCoverageResultcorrelates data by session, producer, scope, metric, and custom metric name; duplicate full keys use last-write-wins while preserving stable order.CoverageThresholdFailed(14), while honoring--ignore-exit-code 14.Tests
main.Coverage capabilities
ITestCoverageCapabilitiesand inspectEnabledProducerUidsfrom a session/data-consumer callback. This lets a report generator detect whether another enabled extension declares coverage messages and emit a warning when none is available.testing.supportsTestCoverageMessages.