Uh oh!
There was an error while loading. Please reload this page.
Add --retry-failed-tests-delay option to MTP retry package - #7840
Conversation
Agent-Logs-Url: https://github.com/microsoft/testfx/sessions/b65299ab-c298-41e1-b995-33ae9f177b0b Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
--retry-failed-tests-delay option to MTP retry packageUh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds a configurable delay between retry attempts for the retry-failed-tests extension to reduce flakiness for external-system-dependent tests.
Changes:
- Introduces
--retry-failed-tests-delayCLI option with unit-aware timespan parsing and validation. - Applies an inter-attempt
Task.DelayinRetryOrchestratorand strips the option from forwarded child-process args. - Updates help text, package docs, resources, and adds unit tests for option validation.
Show a summary per file
| File | Description |
|---|---|
| test/UnitTests/Microsoft.Testing.Extensions.UnitTests/RetryTests.cs | Adds unit tests for delay option parsing/validation and dependency on --retry-failed-tests. |
| test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Services/DesktopTestSourceHostTests.cs | Adjusts nullability usage (null!) in mocks. |
| test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/HelpInfoAllExtensionsTests.cs | Updates expected help output to include the new delay option. |
| src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs | Removes delay arg from forwarded args; parses delay option and delays between attempts. |
| src/Platform/Microsoft.Testing.Extensions.Retry/RetryCommandLineOptionsProvider.cs | Registers the new option and validates dependency + timespan format. |
| src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.zh-Hant.xlf | Adds new resource strings for delay option description/error (untranslated “new” entries). |
| src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.zh-Hans.xlf | Adds new resource strings for delay option description/error (untranslated “new” entries). |
| src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.tr.xlf | Adds new resource strings for delay option description/error (untranslated “new” entries). |
| src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ru.xlf | Adds new resource strings for delay option description/error (untranslated “new” entries). |
| src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.pt-BR.xlf | Adds new resource strings for delay option description/error (untranslated “new” entries). |
| src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.pl.xlf | Adds new resource strings for delay option description/error (untranslated “new” entries). |
| src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ko.xlf | Adds new resource strings for delay option description/error (untranslated “new” entries). |
| src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ja.xlf | Adds new resource strings for delay option description/error (untranslated “new” entries). |
| src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.it.xlf | Adds new resource strings for delay option description/error (untranslated “new” entries). |
| src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.fr.xlf | Adds new resource strings for delay option description/error (untranslated “new” entries). |
| src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.es.xlf | Adds new resource strings for delay option description/error (untranslated “new” entries). |
| src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.de.xlf | Adds new resource strings for delay option description/error (untranslated “new” entries). |
| src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.cs.xlf | Adds new resource strings for delay option description/error (untranslated “new” entries). |
| src/Platform/Microsoft.Testing.Extensions.Retry/Resources/ExtensionResources.resx | Adds delay option description and invalid-argument error string. |
| src/Platform/Microsoft.Testing.Extensions.Retry/PACKAGE.md | Documents the new delay feature and CLI option usage. |
Copilot's findings
- Files reviewed: 20/20 changed files
- Comments generated: 4
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Amaury Levé (Evangelink)
left a comment
There was a problem hiding this comment.
Summary
Workflow: Test Expert Reviewer 🧪
Date: 2026-05-11
Repository: microsoft/testfx
Key Findings
[Critical — will cause test failure]
HelpInfoAllExtensionsTests.cs: The--helpoutput test was updated for--retry-failed-tests-delay, but theInfo_WithAllExtensionsRegistered_OutputFullInfoContenttest was not. BecauseAssertOutputMatchesLinesperforms sequential line-by-line matching, the test will fail in CI — the actual--infooutput now includes the delay option underRetryCommandLineOptionsProvider, but the expected pattern jumps straight toTerminalTestReporterCommandLineOptionsProvider. Four lines need to be inserted in the pattern.[Minor — coverage gap]
RetryTests.cs(IsInvalid_If_InvalidTimeSpan_Is_Provided_For_DelayOption): The whitespace-only input (" ") takes a distinct early-return path inTimeSpanParser.TryParsebut is not included in the[DataRow]set.[Moderate — missing behavioral coverage] Neither the new unit tests nor the existing
RetryFailedTestsTests.csintegration tests verify the actual delay behaviour inRetryOrchestrator: thatTask.Delayis applied between retry attempts (not before the first), and that--retry-failed-tests-delayis stripped from the child-process argument list.
Recommendations
- Add the
--retry-failed-tests-delayblock to the--infoexpected-output string inHelpInfoAllExtensionsTests.cs(around line 342, after the--retry-failed-tests-max-testsentry). - Add
[DataRow(" ")]toIsInvalid_If_InvalidTimeSpan_Is_Provided_For_DelayOption. - Add an acceptance or unit test that exercises the orchestrator's delay and arg-stripping logic end-to-end.
Generated by Test Expert Reviewer
🧪 Test quality reviewed by Test Expert Reviewer 🧪
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…DataRow Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Amaury Levé (Evangelink)
left a comment
There was a problem hiding this comment.
Summary
Workflow: Expert Code Reviewer
Date: 2026-05-11
Repository: microsoft/testfx
Key Findings
[Defensive] TimeSpanParser.Parse in orchestrator path (RetryOrchestrator.cs:158)
The orchestrator calls TimeSpanParser.Parse (which throws FormatException) rather than the TryParse pattern used elsewhere in the same method. No bounds check on retryDelayArgs before [0] access either, inconsistent with how cmdRetries is guarded at line 98. Low practical risk since validation runs first, but adds a latent uncaught-exception path.
[Resources] Pipe server created before delay fires (RetryOrchestrator.cs:181 / 282)RetryFailedTestsPipeServer (OS named-pipe listener) is created ~100 lines before the Task.Delay fires. For large delays (minutes/hours), the pipe holds OS resources for the entire wait period before the child process is launched. Moving the delay to the top of the loop body (immediately after attemptCount++) would scope the pipe server to only the window where it's needed.
Positive Observations
- Correctness of the retry-delay logic is sound: delay correctly skips attempt 1 (
attemptCount > 1), fires before each subsequent attempt, and appliesConfigureAwait(false)throughout. - Cancellation token is correctly threaded into
Task.Delay— cancellation during the wait will propagate asOperationCanceledException, which is the expected behavior for this framework. - Argument stripping (
indexToCleanup) correctly removes both the option flag and its value, consistent with all other stripped options. - Validation in
RetryCommandLineOptionsProvideris complete: dependency on--retry-failed-tests, format validation viaTryParse, and test coverage for valid/invalid inputs. TimeSpanParser.TryParsecorrectly rejects empty strings and invalid formats per the new unit tests.
Overall Assessment
The implementation is logically correct and well-structured. Both findings are minor defensive/resource concerns rather than correctness bugs. No threading issues, security vulnerabilities, or public API breaking changes were identified.
🧠 Reviewed by Expert Code Reviewer
🧠 Reviewed by Expert Code Reviewer 🧠
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
…tion Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Uh oh!
There was an error while loading. Please reload this page.
…clude supported range The error message now mentions the supported range (non-negative and no greater than 2147483647ms / ~24.20:31:23.647) to clarify that syntactically valid but out-of-range values like '25d' are also rejected. Addresses review comment: #7840 (comment) Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com>
Amaury Levé (Evangelink)
commented
May 13, 2026
Copilot address review comments |
The open review comment about the resource string was addressed in commit |
…eptance test The MTP --info output sorts options alphabetically per provider, so --retry-failed-tests-delay must appear between --retry-failed-tests and --retry-failed-tests-max-percentage, not after --retry-failed-tests-max-tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Uh oh!
There was an error while loading. Please reload this page.
The retry extension had no way to introduce a wait between retry attempts, making it less useful for tests interacting with external systems (message queues, databases, etc.) where a cooldown period reduces flakiness.
Changes
--retry-failed-tests-delay: accepts a timespan value using the same unit-aware format as--hangdump-timeout(e.g.200,1s,2.5m,1h; default unit is milliseconds)RetryCommandLineOptionsProvider: registers the option, validates it requires--retry-failed-tests, validates the argument viaTimeSpanParser.TryParse, and enforces a valid range (non-negative, no greater thanint.MaxValuemilliseconds — theTask.Delaymaximum)RetryOrchestrator: strips the delay arg from arguments forwarded to child processes (with a bounds check before addingargIndex + 1to the cleanup list); appliesTask.Delayat the top of the retry loop (afterattemptCount++, before any per-attempt resources are allocated), skipping the first attempt; usesTryParsewith aLength > 0guard instead ofParsefor defensive handling200) alongside unit-suffixed examplesRetryFailedTests_WithDelay_StripsDelayFromChildArgs) that verifies the option is correctly stripped from child-process arguments end-to-endUsage