{"id":4760,"date":"2026-08-06T18:00:54","date_gmt":"2026-08-06T18:00:54","guid":{"rendered":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2026\/08\/06\/test-reporting-in-microsoft-testing-platform-from-red-build-to-root-cause\/"},"modified":"2026-08-06T18:00:54","modified_gmt":"2026-08-06T18:00:54","slug":"test-reporting-in-microsoft-testing-platform-from-red-build-to-root-cause","status":"publish","type":"post","link":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2026\/08\/06\/test-reporting-in-microsoft-testing-platform-from-red-build-to-root-cause\/","title":{"rendered":"Test reporting in Microsoft.Testing.Platform: from red build to root cause"},"content":{"rendered":"<p>When a test fails in CI, \u201cthe build is red\u201d is only the starting point. The useful questions are whether this<br \/>\nchange caused the failure, whether the test has failed before, and where to find the evidence. If answering<br \/>\nthem means searching a job log, downloading an artifact, and finding the teammate who remembers how that test<br \/>\nbehaved last month, the report has not done enough.<\/p>\n<p>MTP reporting shortens the path from a failed build to the decision a developer or reviewer needs to make.<\/p>\n<p><a href=\"https:\/\/aka.ms\/mtp-overview\">Microsoft.Testing.Platform (MTP)<\/a> powers<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/unit-testing-with-dotnet-test\"><code>dotnet test<\/code><\/a>, the Test Explorer<br \/>\nin Visual Studio and Visual Studio Code, and test runs in CI. Over the past year its reporting has been closing<br \/>\nthat gap \u2014 putting failures where reviewers already work, and preserving the evidence when a run falls over.<\/p>\n<p>This works on whichever test framework you already use: MTP is supported by<br \/>\n<a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/mtp-adoption-frameworks\/\">MSTest, NUnit, xUnit.net, TUnit and Expecto<\/a>.<br \/>\nMost capabilities in this post require MTP 2.3.0 or later. The examples were validated with <code>MSTest.Sdk<\/code> 4.3.3<br \/>\nand MTP 2.3.3; the GitHub Actions, JUnit and CTRF reporters currently ship as preview packages.<br \/>\nMost of what follows is provider-independent, but two of the strongest features read your build history, and<br \/>\nthat part is Azure DevOps only today:<\/p>\n<table>\n<thead>\n<tr>\n<th>Capability<\/th>\n<th>GitHub Actions<\/th>\n<th>Azure DevOps<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Inline failure annotations and job summary<\/td>\n<td>Yes<\/td>\n<td>Yes<\/td>\n<\/tr>\n<tr>\n<td>Live result publishing while the run is going<\/td>\n<td>Not yet<\/td>\n<td>Yes<\/td>\n<\/tr>\n<tr>\n<td>Flaky-vs-regression history, quarantine, slow-test history<\/td>\n<td>Not yet<\/td>\n<td>Yes<\/td>\n<\/tr>\n<tr>\n<td>Crash-resilient reports, report formats, JSON discovery<\/td>\n<td>Provider-independent<\/td>\n<td>Provider-independent<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Start with inline reporting on either provider: it moves the next failure out of the raw log. If you use Azure<br \/>\nDevOps, add history-based triage next so reviewers can distinguish a new regression from a recurring failure.<\/p>\n<h2>Put the failure where the author is already looking<\/h2>\n<p>A report that lands in an artifact is a report someone has to go and fetch. Both providers can surface results<br \/>\ninline instead, and MTP now emits the annotation format each one understands natively.<\/p>\n<p>Enable <a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/microsoft-testing-platform-test-reports#github-actions-reports\"><code>--report-gh<\/code><\/a><br \/>\nin a GitHub Actions job and a failing test becomes an annotation on the line of code that failed. Skipped tests<br \/>\nappear as warnings, each assembly is collapsed into its own log group, and the same run writes a summary straight<br \/>\nto the workflow page:<\/p>\n<p><img data-opt-id=1428738293  fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2026\/08\/github-actions-test-summary.webp\" alt=\"A failed GitHub Actions test job with the MTP test run summary\" \/><\/p>\n<p>The failure is visible from the job page and the pull request without downloading a report artifact.<br \/>\nAnnotations, log groups, the summary and slow-test notices can each be configured independently.<\/p>\n<p>Azure DevOps has the same shape behind<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/microsoft-testing-platform-test-reports#azure-devops-reports\"><code>--report-azdo<\/code><\/a>,<br \/>\nand it offers something GitHub Actions doesn\u2019t have yet. With <code>--publish-azdo-test-results<\/code>, results stream into<br \/>\nthe Tests tab <em>while the run is still going<\/em> \u2014 instead of arriving from a separate publish step that only runs if<br \/>\nthe job survives to reach it. The two are independent: <code>--report-azdo<\/code> handles annotations and logging,<br \/>\n<code>--publish-azdo-test-results<\/code> handles the Tests tab, and either works alone.<\/p>\n<h2>Azure DevOps: tell a genuine regression from a known flake<\/h2>\n<p>This is the central decision that build history unlocks: not only <em>which<\/em> test failed, but whether the current<br \/>\nchange is likely to have caused it.<\/p>\n<p>In a large suite, intermittently failing tests train reviewers to read red as background noise. Once \u201cprobably<br \/>\njust flaky\u201d is the reasonable first guess, real regressions inherit the same shrug \u2014 and the cost isn\u2019t the<br \/>\nflaky tests, it\u2019s the response time on everything else.<\/p>\n\n<div class=\"alert alert-primary\">\n<p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Info\"><\/i><strong>Azure DevOps only<\/strong><\/p>\n<p>The build-history annotations, known-flaky demotion, quarantine and history-based slow-test detection in this section are Azure DevOps-only. The GitHub Actions reporter doesn\u2019t offer them yet.<\/p><\/div>\n<p>Azure DevOps already exposes this evidence in the Tests tab. In this testfx run, the current build reported no<br \/>\nfailures across 86,406 tests, while the 14-day history still called out one unique failing test:<\/p>\n<p><img data-opt-id=873777660  fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2026\/08\/azure-devops-test-history.webp\" alt=\"Azure DevOps Tests tab showing current results and a failing test in the 14-day history\" \/><\/p>\n<p>For the testfx team, that context narrows the first investigation step: a failure with no history gets immediate<br \/>\nregression attention, while a recurring failure starts with its existing flaky record.<\/p>\n<p>Pass that same 14-day window to the reporter, and it queries the pipeline history and attaches the context to<br \/>\neach failure:<\/p>\n<pre><code class=\"language-bash\">dotnet test --report-azdo --report-azdo-flaky-history 14<\/code><\/pre>\n<p>A test that has been failing on and off for two weeks is labelled with its record:<\/p>\n<pre><code class=\"language-text\">[flaky: failed 3\/20 in last 14d]<\/code><\/pre>\n<p>A test with no such history gets the label that matters:<\/p>\n<pre><code class=\"language-text\">[REGRESSION]<\/code><\/pre>\n<p>That turns \u201csomeone should look at this eventually\u201d into \u201cthis pull request broke something,\u201d and it reaches<br \/>\nthe reviewer at the point of decision instead of depending on who remembers what. If you want CI to act on it<br \/>\nrather than merely say it, <code>--report-azdo-demote-known-flaky<\/code> turns known-flaky failures into warnings while<br \/>\nregressions stay errors.<\/p>\n<p>In the testfx pipeline we use the history annotations but leave automatic demotion off, so every failure stays<br \/>\nblocking and history only guides triage. Other teams will reasonably choose to demote. The decision worth<br \/>\nmaking explicitly is whether history should inform a reviewer or change CI severity on its own.<\/p>\n<p>The same history powers slow-test detection. Instead of one threshold that is wrong for every project,<br \/>\n<code>--report-azdo-slow-test-history<\/code> compares each test against its own past. The threshold is a configurable<br \/>\nmultiple over a minimum number of runs, so a single cold start won\u2019t trip it.<\/p>\n<h2>Keep the evidence when the run crashes<\/h2>\n<p>History helps determine whether a failure is new, but triage still stalls if the run loses the evidence needed<br \/>\nto investigate it. The run you most need a report from is the one that died. That used to be the run that<br \/>\nproduced nothing, because results were serialized at the end.<\/p>\n<p>TRX results are now streamed to disk as they are produced, so a hard crash no longer takes the whole report<br \/>\nwith it. Pair <code>--report-trx<\/code> with the<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/microsoft-testing-platform-crash-hang-dumps\">crash-dump extension<\/a><br \/>\nand the run is supervised by a controller process that finalises the partial report when the host dies:<\/p>\n<pre><code class=\"language-bash\">dotnet test --report-trx --crashdump<\/code><\/pre>\n<p>You get a valid TRX containing every test that completed, plus a console list of the ones that didn\u2019t:<\/p>\n<pre><code class=\"language-text\">The following tests were still running when the test host crashed:\n[00:00:00] D_crash_the_host<\/code><\/pre>\n<p>That names the test that took the process down, without rerunning the suite to find it. The extension also<br \/>\nwrites a <code>*.crash.sequence.log<\/code> recording every test start and end, so a test that started and never finished<br \/>\nis unambiguous even when several were running in parallel.<\/p>\n<p>Attachments got the same treatment. Crash dumps, hang dumps and extension artifacts are no longer silently<br \/>\ndropped on .NET Framework when the path exceeds the Windows <code>MAX_PATH<\/code> limit, and an attachment that can\u2019t be<br \/>\ncopied is now surfaced on the console rather than only inside the TRX file. An incomplete run is now <em>visibly<\/em><br \/>\nincomplete, instead of a green-looking report with the evidence quietly missing.<\/p>\n<h2>One run, reports for people and tools<\/h2>\n<p>Choose the output based on who consumes it. Use TRX for .NET tooling, HTML for direct inspection, and JUnit or<br \/>\nCTRF for dashboards and cross-stack automation. A single run can enable any combination, removing the<br \/>\nformat-conversion step teams often wire into their pipelines.<\/p>\n<table>\n<thead>\n<tr>\n<th>Format<\/th>\n<th>Enable with<\/th>\n<th>Package<\/th>\n<th>Status<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>TRX<\/td>\n<td><code>--report-trx<\/code><\/td>\n<td><a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Testing.Extensions.TrxReport\"><code>Microsoft.Testing.Extensions.TrxReport<\/code><\/a><\/td>\n<td>Stable<\/td>\n<\/tr>\n<tr>\n<td>HTML<\/td>\n<td><code>--report-html<\/code><\/td>\n<td><a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Testing.Extensions.HtmlReport\"><code>Microsoft.Testing.Extensions.HtmlReport<\/code><\/a><\/td>\n<td>Stable<\/td>\n<\/tr>\n<tr>\n<td>JUnit XML<\/td>\n<td><code>--report-junit<\/code><\/td>\n<td><a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Testing.Extensions.JUnitReport\"><code>Microsoft.Testing.Extensions.JUnitReport<\/code><\/a><\/td>\n<td>Preview<\/td>\n<\/tr>\n<tr>\n<td>CTRF JSON<\/td>\n<td><code>--report-ctrf<\/code><\/td>\n<td><a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Testing.Extensions.CtrfReport\"><code>Microsoft.Testing.Extensions.CtrfReport<\/code><\/a><\/td>\n<td>Preview<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><a href=\"https:\/\/ctrf.io\/\">CTRF<\/a> is worth knowing about if you aggregate results across languages: it\u2019s a shared JSON<br \/>\nschema, so .NET reports into the same shape as the rest of a polyglot estate.<\/p>\n<p>Only TRX and JUnit are formats a CI system parses into a results view. HTML and CTRF are for people and<br \/>\ndashboards, so they show up as downloadable artifacts instead \u2014 and on Azure DevOps,<br \/>\n<code>--report-azdo-upload-artifacts files<\/code> collects them automatically. Pick TRX or JUnit when something downstream<br \/>\nreads the results; add HTML or CTRF for whoever has to look at them.<\/p>\n<p>Report names no longer collide either. Each reporter takes a <code>--report-&lt;format&gt;-filename<\/code> accepting<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/microsoft-testing-platform-test-reports#report-file-names\">build-specific placeholders<\/a><br \/>\nsuch as <code>{asm}<\/code> and <code>{tfm}<\/code>, resolved under the results directory:<\/p>\n<pre><code class=\"language-bash\">dotnet test --report-trx --report-trx-filename \"reports\/{asm}_{tfm}_{time}.trx\"<\/code><\/pre>\n<p>Left alone, TRX, HTML and JUnit now default to a deterministic <code>&lt;asm&gt;_&lt;tfm&gt;_&lt;arch&gt;<\/code> name. If you multi-target,<br \/>\n<code>net8.0<\/code> and <code>net8.0-windows<\/code> write separate files instead of reporting over each other \u2014 a quiet data-loss bug<br \/>\nin matrix builds that is worth checking for in your current setup.<\/p>\n<h2>Stable output for automation<\/h2>\n<p>People need actionable context in the pull request; automation needs the same context in a stable, structured<br \/>\nformat. Scripts, dashboards, IDE integrations and coding agents cannot reliably consume terminal prose.<\/p>\n<p><code>--list-tests json<\/code> emits a schema-versioned document describing every discovered test, down to its source<br \/>\nlocation:<\/p>\n<pre><code class=\"language-json\">{\n  \"schemaVersion\": 1,\n  \"tests\": [\n    {\n      \"uid\": \"11a3aade-7a31-8389-89ce-eab6ff0db7f3\",\n      \"displayName\": \"Total_includes_shipping\",\n      \"location\": { \"file\": \"CheckoutTests.cs\", \"lineStart\": 13, \"lineEnd\": 13 }\n    }\n  ]\n}<\/code><\/pre>\n<p>That schema is a stable input for test selection, impact analysis or IDE integration, instead of scraping<br \/>\nconsole text that changes between releases.<\/p>\n<p>MTP also adapts its own output for these consumers. In an agent or LLM environment it suppresses the banner,<br \/>\nANSI escapes and progress animation, and defaults <code>--show-stdout<\/code> and <code>--show-stderr<\/code> to <code>failed<\/code>, so what<br \/>\ncomes back is results rather than redrawn progress bars. You can set the same behaviour by hand \u2014 the platform<br \/>\nhonors <code>NO_COLOR<\/code>, and exposes <code>--ansi<\/code> and <code>--progress<\/code> for the rest.<\/p>\n<h2>Try it today<\/h2>\n<ol>\n<li>Confirm that one test project runs MTP 2.3 or later.<\/li>\n<li>Enable the reporter for your CI provider through <code>MSTest.Sdk<\/code> or a direct package reference.<\/li>\n<li>Add <code>dotnet test --report-gh<\/code> in GitHub Actions or <code>dotnet test --report-azdo<\/code> in Azure DevOps.<\/li>\n<li>Use the next failure to check whether the report reduced the time you spent searching logs.<\/li>\n<\/ol>\n<h3>Scale it across a repository<\/h3>\n<p>Once you have chosen a reporting policy, keep it in the repository rather than everyone\u2019s shell history. Every<br \/>\noption in the<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/microsoft-testing-platform-cli-options\">MTP CLI reference<\/a> can<br \/>\nlive in a checked-in<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/microsoft-testing-platform-config#cli-options-in-testconfigjson\"><code>testconfig.json<\/code><\/a><br \/>\nbeside your test project, under <code>commandLineOptions<\/code>:<\/p>\n<pre><code class=\"language-json\">{\n  \"commandLineOptions\": {\n    \"report-trx\": true,\n    \"report-html\": true,\n    \"report-azdo\": true,\n    \"report-azdo-flaky-history\": 14\n  }\n}<\/code><\/pre>\n<p>Local and CI runs then produce the same reports by default, and a developer can still override any of it from<br \/>\nthe command line. Misspelled settings fail at startup with a message naming the file, rather than being<br \/>\nsilently ignored:<\/p>\n<pre><code class=\"language-text\">In testconfig.json under 'commandLineOptions': Unknown option '--report-trxx'<\/code><\/pre>\n<p>For a repo-wide rollout:<\/p>\n<ul>\n<li>\n<p><strong>Centralize once you\u2019ve decided.<\/strong> With <code>MSTest.Sdk<\/code> each reporter is an MSBuild property, so one<br \/>\n<code>Directory.Build.props<\/code> applies your policy to every test project in the repo:<\/p>\n<pre><code class=\"language-xml\">&lt;Project&gt;\n&lt;PropertyGroup&gt;\n  &lt;EnableMicrosoftTestingExtensionsHtmlReport&gt;true&lt;\/EnableMicrosoftTestingExtensionsHtmlReport&gt;\n  &lt;EnableMicrosoftTestingExtensionsAzureDevOpsReport&gt;true&lt;\/EnableMicrosoftTestingExtensionsAzureDevOpsReport&gt;\n&lt;\/PropertyGroup&gt;\n&lt;\/Project&gt;<\/code><\/pre>\n<p>The properties follow one pattern (<code>EnableMicrosoftTestingExtensions<\/code> + reporter name), and<br \/>\n<code>&lt;TestingExtensionsProfile&gt;AllMicrosoft&lt;\/TestingExtensionsProfile&gt;<\/code> switches on the stable set in one line \u2014<br \/>\nTRX, HTML, Azure DevOps, GitHub Actions, crash dump, hang dump and retry. JUnit and CTRF stay opt-in.<\/p>\n<\/li>\n<li><strong>On other frameworks, check the version.<\/strong> Outside <code>MSTest.Sdk<\/code> you reference the reporter package<br \/>\ndirectly, and it has to match the MTP version your framework targets. These reporters are built on MTP 2.x,<br \/>\nso adding one to a project on an older framework release fails at startup with a <code>MissingMethodException<\/code>.<br \/>\nMTP 2.x support arrives in <code>MSTest.TestAdapter<\/code> 4.0.0, <code>NUnit3TestAdapter<\/code> 6.0.1, <code>TUnit<\/code> 1.7.16,<br \/>\n<code>YoloDev.Expecto.TestSdk<\/code> 0.16.0, and the <code>xunit.v3<\/code> 4.0 prereleases.<\/li>\n<li><strong>Set the runner opt-in once, at the repo level.<\/strong> Whether <code>dotnet test<\/code> runs your solution through MTP is a<br \/>\nsingle switch \u2014 put it in <code>Directory.Build.props<\/code> so a new project can\u2019t drift out of it. Mixing MTP and<br \/>\nVSTest projects in one solution isn\u2019t supported; on the .NET 10 SDK, running an MTP project through the old<br \/>\nVSTest path fails the build with a link to the opt-in, so any drift surfaces immediately. The<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/migrating-vstest-microsoft-testing-platform\">migration guide<\/a><br \/>\ncovers that switch.<\/li>\n<li><strong>The Azure DevOps history options need a token.<\/strong> <code>--report-azdo-flaky-history<\/code> and<br \/>\n<code>--report-azdo-slow-test-history<\/code> call the Azure DevOps REST API, so pass<br \/>\n<code>SYSTEM_ACCESSTOKEN: $(System.AccessToken)<\/code> to the step. Without it the run continues and simply skips the<br \/>\nhistory annotations.<\/li>\n<\/ul>\n<h3>Replacing your existing publish tasks<\/h3>\n<p>If you own an existing Azure DevOps pipeline, this section shows which publishing tasks you can replace.<br \/>\nLive publishing sends the results it already holds in memory straight to the REST API \u2014 it doesn\u2019t read a TRX,<br \/>\nso there\u2019s no report file to produce or glob for. Together with <code>--report-azdo-upload-artifacts files<\/code>, which<br \/>\npublishes the test results directory as a build artifact, that replaces the tasks most pipelines carry today:<\/p>\n<table>\n<thead>\n<tr>\n<th>Classic task<\/th>\n<th>Replaced by<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>PublishTestResults@2<\/code><\/td>\n<td><code>--publish-azdo-test-results<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>PublishBuildArtifacts@1<\/code> \/ <code>PublishPipelineArtifact@1<\/code><\/td>\n<td><code>--report-azdo-upload-artifacts files<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>PublishCodeCoverageResults@2<\/code><\/td>\n<td>Not replaced \u2014 keep it for the pipeline\u2019s Code Coverage tab<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Coverage is the one to watch. Live publishing does attach <code>.coverage<\/code>, <code>.cobertura.xml<\/code> and <code>.opencover.xml<\/code><br \/>\nto the test run, and failing tests carry their own attachments \u2014 dumps, plus captured stdout and stderr. But<br \/>\nnothing here populates the pipeline\u2019s Code Coverage tab, so keep the step that does that today.<\/p>\n\n<div class=\"alert alert-info\">\n<p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Info\"><\/i><strong>Avoid duplicate test runs<\/strong><\/p>\n<p>Live publishing and a <code>PublishTestResults@2<\/code> task are independent publishers, not two views of one run. If you enable both, Azure DevOps creates two test runs for the build, so pick one.<\/p><\/div>\n<h2>Where reporting goes next<\/h2>\n<p>Line these changes up and a direction appears. Two years ago MTP was a lighter way to execute tests. Today it<br \/>\nputs failures directly into GitHub Actions and Azure DevOps, and publishes results live in Azure DevOps as the<br \/>\nrun happens. It interprets a failure against your own build history, preserves evidence when the host crashes,<br \/>\nand exposes a stable schema to tools that hadn\u2019t been written when the platform shipped. The next round \u2014 live<br \/>\npublishing for GitHub Actions, richer artifact handling, and stable releases for the preview reporters \u2014<br \/>\ncontinues the same shift: from producing a result file to helping a team decide what to do next.<\/p>\n<p>Reporting is a practical place to evaluate MTP, because developers, reviewers and build owners all see the<br \/>\ndifference on day one. Pick the smallest version of it: turn on <code>--report-gh<\/code> or <code>--report-azdo<\/code> in one test<br \/>\nproject and watch where your next failure shows up.<\/p>\n<p>Then tell us what still sends you back to the logs. Several of the options in this post exist because somebody<br \/>\nopened an issue on <a href=\"https:\/\/github.com\/microsoft\/testfx\">the testfx repository<\/a> describing a bad afternoon.<\/p>\n\n<div class=\"d-flex justify-content-center\"><a class=\"cta_button_link btn-primary mb-24\" href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/testing\/microsoft-testing-platform-test-reports\" target=\"_blank\">Add MTP reporting to your CI run<\/a><\/div>\n<p>The post <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/microsoft-testing-platform-reporting\/\">Test reporting in Microsoft.Testing.Platform: from red build to root cause<\/a> appeared first on <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\">.NET Blog<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>When a test fails in CI, \u201cthe build is red\u201d is only the starting point. The useful questions are whether [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4761,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[7],"tags":[],"class_list":["post-4760","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet"],"_links":{"self":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/4760","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/comments?post=4760"}],"version-history":[{"count":0,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/4760\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/media\/4761"}],"wp:attachment":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/media?parent=4760"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/categories?post=4760"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/tags?post=4760"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}