Add acceptance test combining --retry-failed-tests with --treenode-filter#8405
Conversation
…lter Validates issue #5673: when both --retry-failed-tests and --treenode-filter are specified, the orchestrator strips --treenode-filter on retry and replaces it with --filter-uid targeting only the failed tests (filters are replaced, not stacked). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adds an acceptance test to guard against #5673 by ensuring --retry-failed-tests does not stack with an existing --treenode-filter (the retry run must replace the original filter with --filter-uid <failed>).
Changes:
- Added a new acceptance test
RetryFailedTests_WithPreexistingTreeNodeFilter_ReplacesFilterOnRetry. - Updated the generated dummy test asset to register the
--treenode-filtercommand-line option and to honorTreeNodeFilterin its execution logic.
Show a summary per file
| File | Description |
|---|---|
| test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/RetryFailedTestsTests.cs | Adds the new retry+treenode-filter acceptance test and extends the embedded test asset to support TreeNodeFilter. |
Copilot's findings
- Files reviewed: 1/1 changed files
- Comments generated: 1
Code ReviewDimension 13 — Test Completeness & Coverage (MAJOR) ✅ with one minor gapPoint 1 – First attempt honours Point 2 – Retry uses only Missing negative test (minor gap): The sibling Dimension 15 — Code Structure & Simplification (MODERATE) ✅ /
|
Evangelink
left a comment
There was a problem hiding this comment.
Review Summary
10/10 applicable dimensions clean — one optional NIT.
| Dimension | Result |
|---|---|
| Algorithmic Correctness | ✅ LGTM |
| Test Isolation | ✅ LGTM |
| Assertion Quality | ✅ LGTM |
| Flakiness Patterns | ✅ LGTM |
| Test Completeness | 🔵 NIT (see inline) |
| Code Structure | ✅ LGTM |
| Data-Driven Coverage | ✅ LGTM |
| Naming & Conventions | ✅ LGTM |
| Documentation Accuracy | ✅ LGTM |
| Scope & PR Discipline | ✅ LGTM |
The implementation is correct. The IsIncluded filters are mutually exclusive at runtime (the request filter can only be one concrete type), so the AND logic is safe. The sentinel-file mechanism makes the retry deterministic. The one inline note is an optional enhancement to also validate attempt-1 behavior.
Generated by Expert Code Review (on open) for issue #8405 · ● 13.9M
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| // Verify that the retry attempt only ran the failed test (TestMethod1) - i.e. the treenode-filter was | ||
| // dropped and replaced by --filter-uid 1, not stacked on top of it. If the filters had been stacked | ||
| // (or worse, both forwarded as separate options), the second attempt would have failed validation or | ||
| // produced no results. | ||
| // The TRX in the top-level results directory (not under Retries/) is from the last attempt. | ||
| string[] topLevelTrxFiles = Directory.GetFiles(resultDirectory, "*.trx", SearchOption.TopDirectoryOnly); | ||
| Assert.HasCount(1, topLevelTrxFiles); | ||
|
|
||
| string trxContent = File.ReadAllText(topLevelTrxFiles[0]); | ||
| Assert.Contains("TestMethod1", trxContent); | ||
| Assert.DoesNotContain("TestMethod2", trxContent); | ||
| Assert.DoesNotContain("TestMethod3", trxContent); |
| [TestMethod] | ||
| [DynamicData(nameof(TargetFrameworks.NetForDynamicData), typeof(TargetFrameworks))] | ||
| public async Task RetryFailedTests_WithPreexistingTreeNodeFilter_ReplacesFilterOnRetry(string tfm) | ||
| { |
|
@copilot address review comments |
Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Addressed review feedback in 5cd8d5d. I added first-attempt TRX assertions for the treenode-filter retry test, ran the pack build successfully, attempted the targeted acceptance test (blocked by transient package download errors for |
Fixes #5673.
Investigation
The
RetryOrchestrator(src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs:199-203) already strips both--treenode-filterand--filter-uidfrom the child-process arguments when launching a retry attempt, then injects a fresh--filter-uid <failed-uids>. Filters are therefore replaced, not stacked — exactly the concern raised in #5673. This was added as part of the earlier Retry simplification work.What this PR adds
A new acceptance test
RetryFailedTests_WithPreexistingTreeNodeFilter_ReplacesFilterOnRetrythat guards the combined--retry-failed-tests+--treenode-filterflow, mirroring the existingWithPreexistingFilterUid_ReplacesFilterOnRetrytest.To support it, the dummy framework in the test asset now:
AddTreeNodeFilterService(via a smallTreeNodeFilterExtension).TreeNodeFilterin addition toTestNodeUidListFilter, matching nodes against/<DisplayName>paths.The test verifies that:
--treenode-filter "/(TestMethod1|TestMethod2)"(TestMethod1 fails, TestMethod2 passes, TestMethod3 never runs).--treenode-filterand uses only--filter-uid 1(just the failed test).Verification
.\build.cmd -pack -c Debugsucceeded.RetryFailedTests*acceptance tests pass onnet8.0,net10.0andnet462, including the two newWithPreexistingTreeNodeFiltervariants.