Skip to content

Public API for coverage extensions: threshold checks, terminal summary, and exit code in Microsoft.Testing.Platform #9943

Description

@james-newell-forge

Summary

Add a public API in Microsoft.Testing.Platform (MTP) so coverage extensions can perform coverage-threshold checks and surface coverage results in the terminal summary and threshold checks in the process exit code. Adds two message-bus types, three enums, and a new exit code.

Proposed in PR #9896 — filing here so the team can approve the public API shape before it ships (MTP public API is effectively permanent).

Background and Motivation

Today a coverage extension cannot:

  • Enforce a coverage threshold — there's no platform contract to report "coverage X% is below the required Y%", and no way to fail the run for it.
  • Show coverage in the standard terminal summary — the built-in terminal reporter has no coverage concept, so a coverage tool must print its own ad-hoc output.
  • Influence the process exit code — there's no dedicated, ignorable exit code for a threshold failure, so each tool invents its own convention.

Coverage is produced out-of-process: a coverage extension registers as an ITestHostProcessLifetimeHandler (runs in the test-host controller) and publishes these messages after the test host exits; the controller then renders the summary and applies the verdict. A stable public message contract is what lets an external coverage extension plug into that pipeline.

Example coverage extensions that would benefit from this change:

Proposed Feature

New public API in Microsoft.Testing.Platform.Extensions.Messages:

public enum CoverageType { Line = 0, Branch = 1, Method = 2 }
public enum CoverageThresholdStatus { Passed = 0, Failed = 1 }
public enum CoverageThresholdStatistic { Minimum = 0, Total = 1, Average = 2 }

public sealed class TestCoverageMessage : PropertyBagData
{
    public TestCoverageMessage(string moduleName, double value, CoverageType coverageType);
    public string ModuleName { get; }
    public double Value { get; }          // percentage, 0..100
    public CoverageType CoverageType { get; }
}

public sealed class TestCoverageThresholdMessage : PropertyBagData
{
    public TestCoverageThresholdMessage(double value, double threshold,
        CoverageType coverageType, CoverageThresholdStatus status,
        CoverageThresholdStatistic statistic);
    public double Value { get; }
    public double Threshold { get; }
    public CoverageType CoverageType { get; }
    public CoverageThresholdStatus Status { get; }
    public CoverageThresholdStatistic Statistic { get; }
}

Plus a new exit code Microsoft.Testing.Platform.Helpers.ExitCode.CoverageThresholdFailed = 14.

Behavior: coverage extensions publish these messages; the terminal device renders a coverage summary + threshold results, and a failed threshold on an otherwise-successful run sets exit code 14, routed through the existing --ignore-exit-code policy so --ignore-exit-code 14 suppresses it.

Alternative Designs

  • No platform API (coverage extension owns everything). Rejected — a tool can't integrate with the built-in terminal reporter or --ignore-exit-code, and every tool diverges on output and exit codes.
  • In-process coverage production. Rejected — collectors run in the controller around the test-host process, so the out-of-process model is the realistic one.
  • Reuse a generic/combined message. Rejected — coverage results and threshold verdicts are distinct, independently produced concepts that benefit from strongly-typed contracts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs/triageNeeds triage by a maintainer.

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions