Surface and re-print handshake failures in dotnet test#54501
Surface and re-print handshake failures in dotnet test#54501Evangelink wants to merge 2 commits into
Conversation
Follow-up to PR #54437 addressing review feedback (#54437 (review)) and remaining concerns from #51608: - Reword the misleading 'race' comment in AssemblyRunCompleted. Controller- only handshake is already routed to HandshakeFailure by TestApplicationHandler.OnTestProcessExited, so the defensive branch is unreachable in normal operation; the new comment reflects that. - Track each HandshakeFailure (assembly, tfm, exit code, stdout, stderr) in a List<T> guarded by a lock so we can re-print the details at end of run. - Fix summary-line precedence so 'Failed!' wins over 'Zero tests ran' when every assembly failed its handshake (previously the headline implied a benign empty run). - Append a 'Handshake failures:' recap section after the summary listing each failing assembly with its exit code and captured output so users do not have to scroll to find the cause. - Extract CapturingConsole into a shared test helper and add tests covering the recap, multiple-failure ordering, no-failure path, and the existing defensive AssemblyRunCompleted branch. - Add HandshakeFailuresHeader resource string (xlf files auto-generated via /t:UpdateXlf, left in state='new' for translators). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Follow-up to #54437 that makes test-host handshake failures more discoverable. The reporter now records every handshake failure, re-prints a "Handshake failures:" recap at the end of the run, and fixes the summary precedence so a handshake-only failure no longer prints "Zero tests ran" as the headline.
Changes:
- Track handshake failures in a lock-guarded list and append a recap section after the test run summary.
- Reorder summary branches so
anyTestFailed || anyAssemblyFailedtakes precedence overallTestsWereSkipped. - Add a new localized
HandshakeFailuresHeaderresource (resx + 13 xlf) and extractCapturingConsoleinto a shared test helper with new coverage.
Show a summary per file
| File | Description |
|---|---|
| src/Cli/dotnet/Commands/Test/MTP/Terminal/TerminalTestReporter.cs | Records handshake failures, emits end-of-run recap, fixes summary precedence, reworded defensive comment. |
| src/Cli/dotnet/Commands/CliCommandStrings.resx | Adds HandshakeFailuresHeader string with translator comment. |
| src/Cli/dotnet/Commands/xlf/CliCommandStrings.*.xlf (13 files) | Regenerated xlf entries with state="new". |
| test/dotnet.Tests/CommandTests/Test/CapturingConsole.cs | Extracted shared IConsole test double. |
| test/dotnet.Tests/CommandTests/Test/TerminalTestReporterTests.cs | New tests covering recap, multiple failures, no-failure path. |
| test/dotnet.Tests/CommandTests/Test/TestApplicationHandlerTests.cs | Removes the now-shared inner CapturingConsole. |
Copilot's findings
- Files reviewed: 18/18 changed files
- Comments generated: 0
|
I won't be able to review all the changes here, but worth getting some review from @nohwnd. |
| /// the actionable cause. | ||
| /// </summary> | ||
| [Fact] | ||
| public void TestExecutionCompleted_AfterHandshakeFailure_ReprintsFailureDetailsAtEndOfRun() |
There was a problem hiding this comment.
I prefer to see integration tests instead of unit tests.
The integration test could try to simulate the scenario by having a custom test host controller extension that crashes or whatever it was that gets us in the bad state. I would like to see the E2E behavior, preferably have a "before" and "after" views.
Per @Youssef1313 and @nohwnd review feedback on PR #54501, replace the recap-related unit tests in TerminalTestReporterTests with end-to-end coverage in GivenDotnetTestRunsConsoleAppWithoutHandshake that exercises the user-visible behavior through 'dotnet test'. - Expand GivenDotnetTestRunsConsoleAppWithoutHandshake with a new test asserting stdout contains the 'Handshake failures:' recap header, the recap section identifies the failing assembly, and the summary headline reads 'Failed!' rather than 'Zero tests ran' (scoped to the summary line only, since the per-assembly progress can legitimately contain 'Zero tests ran'). - Remove the three recap-related unit tests (TestExecutionCompleted_AfterHandshakeFailure_ReprintsFailureDetailsAtEndOfRun, TestExecutionCompleted_WithMultipleHandshakeFailures_ListsAllOfThemAtEndOfRun, TestExecutionCompleted_WithNoHandshakeFailures_DoesNotEmitRecapHeader) now covered E2E. - Keep AssemblyRunCompleted_WhenExecutionIdUnknown_DoesNotThrowAndReportsHandshakeFailure as a defensive unit test — it guards an unreachable back-stop branch that cannot be exercised end-to-end. - Keep OnTestProcessExited_WhenOnlyControllerHandshakeReceived_RoutesToHandshakeFailureWithModuleContext in TestApplicationHandlerTests as a defensive routing test. Guards the new text assertions with SdkTestContext.IsLocalized() per repo convention. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Thanks @Youssef1313 and @nohwnd for the feedback! Addressed in 31f0c99. Changes:
Captured stdout from a green run on my box: Kept as defensive unit tests (cannot be exercised E2E):
Let me know if you'd still like a dedicated controller-crash test asset; happy to add one if you think the routing-level unit test isn't enough. |
Follow-up to #54437 addressing the review feedback from @Youssef1313 and the remaining concerns from #51608:
Changes
AssemblyRunCompleted. Controller-only handshakes are already routed toHandshakeFailurebyTestApplicationHandler.OnTestProcessExited, so the defensive branch is unreachable in normal operation. The new comment reflects that — it stays as belt-and-suspenders for stray completions after_assemblies.Clear()or future regressions.List<T>guarded by a lock so we can re-print details at end of run.anyAssemblyFailednow takes precedence overallTestsWereSkipped. Previously a pure handshake-failure run (zero tests registered) printed "Zero tests ran" as the headline, masking the failure; it now correctly prints "Failed!".CapturingConsoleinto a shared helper and added coverage for the recap, multiple-failure ordering, the no-failure path, and the existing defensiveAssemblyRunCompletedbranch.Localization
The new
HandshakeFailuresHeaderresource string was added toCliCommandStrings.resxwith a descriptive<comment>. The 13xlffiles were regenerated via/t:UpdateXlf /p:UpdateXlfOnBuild=true(do not hand-edit — entries are instate="new"for translators per the repo workflow).Verification
cc @Youssef1313