Skip to content

--retry-failed-tests leaves only the last attempt's report in the results directory, so TRX/CTRF/JUnit under-report the run #10293

Description

@Evangelink

Describe the bug

When --retry-failed-tests is used, the report files left in the results directory (TRX, CTRF, JUnit, HTML) describe only the final attempt, not the run as a whole. The earlier attempts' reports are kept, but tucked away under Retries/<id>/<n>/.

Concretely, a 4-test suite that needed 4 attempts leaves a CTRF report in the results directory claiming the run had exactly one test.

The orchestrator moves the last attempt's files verbatim:

https://github.com/microsoft/testfx/blob/main/src/Platform/Microsoft.Testing.Extensions.Retry/RetrySummaryReporter.csMoveArtifactsAsync

Because each retry attempt is filtered down to the previously-failed tests, the last attempt's report is by construction the narrowest one — so the file a CI system picks up is the least representative of the run.

Version used

main (Microsoft.Testing.Extensions.Retry 2.4.0-dev, Microsoft.Testing.Platform 2.4.0-dev), reproduced locally from a fresh build.cmd -pack.

Steps To Reproduce

  1. Create an MTP test app with 4 tests: 2 always pass, 1 fails only on its first run, 1 always fails.

  2. Reference Microsoft.Testing.Extensions.CtrfReport (TRX and JUnit behave the same way).

  3. Run:

    MyTests.exe --retry-failed-tests 3 --results-directory TR --report-ctrf
    
  4. Inspect TR/*.ctrf.json — the file at the top level, not the ones under TR/Retries/.

Resulting layout:

TR\<name>.ctrf.json                       <- from attempt 4 only
TR\Retries\<id>\1\<name>.ctrf.json        <- attempt 1 (all 4 tests)
TR\Retries\<id>\2\<name>.ctrf.json        <- attempt 2 (2 tests)
TR\Retries\<id>\3\<name>.ctrf.json        <- attempt 3 (1 test)

Expected behavior

The report in the results directory should describe the whole run: 4 tests, with the recovered test marked as flaky and its earlier failed attempt(s) recorded.

For CTRF specifically that means summary.tests: 4 and "flaky": 1, with retries / retryAttempts[] populated on the test that recovered — the shape CtrfReportEngine.TestCollapsing.cs already defines.

Actual behavior

The top-level CTRF report describes only attempt 4:

{ "tests": 1, "passed": 0, "failed": 1, "skipped": 0, "pending": 0, "other": 0, "flaky": 0 }

Three of the four tests are absent, and the test that failed-then-passed is not represented at all — neither as passed, nor as flaky.

Additional context

The merging machinery already exists and is used elsewhere; it is simply not wired into the retry orchestrator:

  • CtrfReportMerger.Merge(IReadOnlyList<string>) — pure JSON-level merge, re-derives summary counters from the merged tests[]
  • TrxReportEngine.Merge.Orchestration.cs / .Merge.Summary.cs
  • JUnitSuiteBuilder

So the fix is plausibly "merge the per-attempt reports instead of moving the last one" rather than new format work.

Points to decide while implementing:

  • Collapse vs. concatenate. A naive concatenation would double-count tests that ran in several attempts. The merge needs the same per-uid collapse rule CTRF's CollapseAttempts uses (last attempt wins, earlier ones become retry attempts), otherwise summary.tests inflates.
  • Formats without a retry concept. TRX and JUnit have no flaky/retry notion. Collapsing to the final outcome per test is probably right there, but it should be a deliberate decision rather than a side effect.
  • Keep the per-attempt files. The Retries/<id>/<n>/ files are useful for debugging and should stay; this is about what the top-level report says.

Related: the console summary was fixed to report retried and flaky tests correctly in #5362 — so the terminal and the report files currently disagree about the same run.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/mtp-extensionsMTP extensions (TrxReport, Retry, HtmlReport, ...).

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions