Precept 0.10.0

Precept.Reporting.Teams

Microsoft Teams reporting for Precept: one Adaptive Card per run, posted to an incoming webhook — the verdict, the counts, the pass rate, and a link to the build that produced them.

dotnet add package Precept.Reporting.Teams
public sealed class Startup : IPreceptStartup
{
    public void ConfigureServices(IServiceCollection services, PreceptSettings settings) =>
        services.AddPreceptTeamsReporting(teams => teams.Variant = PreceptTeamsCardVariant.Pipeline);
}
{
  "Reporting": {
    "Teams": {
      "Variant": "Pipeline",
      "NotifyOn": "Failure",
      "Title": "Checkout regression",
      "ImageUrl": "https://dev.azure.com/acme/Web/_apis/build/status/nightly",
      "Facts": { "Owner": "Checkout squad" }
    }
  }
}

Variants#

Variant picks the layout — in code as above, or from precept.json, or as PRECEPT_REPORTING__TEAMS__VARIANT for a single run.

Variant Card
Summary (default) Verdict header, the counts as tiles, the pass rate, the environment. No failure messages.
Compact One line: verdict, pass rate, duration, and the button.
Detailed Summary, then the failed tests and their messages — MaxFailuresListed and MaxFailureMessageLength cap it.
Pipeline Summary, then the build: pipeline, build number, branch, commit, who queued it.

The pipeline facts are read from the agent's own variables (Azure DevOps and GitHub Actions), so nothing is configured into the test project and a run off an agent renders the summary it is built on rather than a table of blanks. The same detection gives every variant its button: leave RunUrl unset and the card links to the build that ran the suite.

The card links the run's other reports. Register Precept.Reporting.ReportPortal or Precept.Reporting.AzureDevOps alongside it and the card grows a button per destination — Open ReportPortal, Open Azure DevOps — because each of those reporters posts what it opened to PreceptRunLinks as soon as it has an address. Nothing to configure: those ids are assigned while the run is running. One button per service, so the detected build steps aside for an Azure DevOps test run rather than sitting next to it. "LinkToOtherReports": false turns them off, and a reporter of your own can post to the same board and be linked the same way. See linking a run's reports to each other.

ImageUrl puts a picture on the card — a pipeline status badge, a team logo. It must be an https address every reader's Teams client can fetch without signing in, because the card renders in their client and not on the agent. ImagePlacement takes Thumbnail (the default, beside the heading), Banner (full width) or None, which is how an overlay drops the image without losing the URL.

The webhook URL is a credential — anyone holding it can post to the channel — so supply it from CI as PRECEPT_REPORTING__TEAMS__WEBHOOKURL rather than committing it. Create it from the channel's Workflows connector; the payload is the Adaptive Card envelope a workflow URL expects, not the retired Office 365 connector's MessageCard.

Cards are posted from a build agent only, so a channel hears about the pipeline's runs and not about every run somebody starts while writing a scenario. A developer's run posts nothing and asks for nothing — the reporter is never started, so a missing webhook is not an error there. Add { "Reporting": { "CiOnly": false } } to precept.local.json to post from your own machine while working on the card, and see CI and local runs for how a run is recognised as CI.

One HTTP call, after the last test, built from the summary Precept already keeps. Nothing is sent per test: a channel does not want one message per scenario, and reporting never runs on a test's thread in any case.

NotifyOn takes Always, Failure or FailureOrFlaky — the last of which is how a green-but-retried run still gets noticed.


Part of Precept, a .NET 10 test automation framework. Full documentation: reporting · configuration · writing your own reporter

Precept 0.10.0 · MIT · © 2026

Esc