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.cs — MoveArtifactsAsync
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
-
Create an MTP test app with 4 tests: 2 always pass, 1 fails only on its first run, 1 always fails.
-
Reference Microsoft.Testing.Extensions.CtrfReport (TRX and JUnit behave the same way).
-
Run:
MyTests.exe --retry-failed-tests 3 --results-directory TR --report-ctrf
-
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.
Describe the bug
When
--retry-failed-testsis 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 underRetries/<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.cs —
MoveArtifactsAsyncBecause 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 freshbuild.cmd -pack.Steps To Reproduce
Create an MTP test app with 4 tests: 2 always pass, 1 fails only on its first run, 1 always fails.
Reference
Microsoft.Testing.Extensions.CtrfReport(TRX and JUnit behave the same way).Run:
Inspect
TR/*.ctrf.json— the file at the top level, not the ones underTR/Retries/.Resulting layout:
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: 4and"flaky": 1, withretries/retryAttempts[]populated on the test that recovered — the shapeCtrfReportEngine.TestCollapsing.csalready 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-derivessummarycounters from the mergedtests[]TrxReportEngine.Merge.Orchestration.cs/.Merge.Summary.csJUnitSuiteBuilderSo 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:
CollapseAttemptsuses (last attempt wins, earlier ones become retry attempts), otherwisesummary.testsinflates.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.