Run the Avalonia tests headless so the suite completes - #1
Merged
Merged
Conversation
The test suite hangs when run as a whole, and three tests fail even when each class is run on its own. Both come from how Avalonia is started for the tests. Each class guards AppBuilder.Setup behind its own class-local flag, but Setup is once-per-process, so the second class to run throws "Setup was already called". And the desktop SetupWithoutStarting never starts a dispatcher loop, so a Dispatcher.UIThread.Invoke from a test can wait for a pump that will never run - which is the hang. Avalonia.Headless.XUnit exists for exactly this: [AvaloniaTestApplication] sets up one headless application per process, and [AvaloniaFact] runs a test on the headless dispatcher thread, so UI work has somewhere to run. Tests that touch controls or windows are marked [AvaloniaFact]; the rest stay plain [Fact]. The per-class EnsureAvalonia helpers are no longer needed. Also means the suite needs no display, so it can run in CI. Before: hangs past 120s, 3 failures logged on the way. After: 39/39 in about a second. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Aug 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First of the PRs offered in #272 — starting here because it's self-contained, and because it makes the other PRs verifiable: right now
dotnet testnever returns, so there's no way to check a change by running the suite.Not a macOS change. I found it while evaluating your branch as the base for a macOS port, but it's platform-independent — the same hang happens on Linux.
The problem
Two symptoms, one cause: the suite hangs when run as a whole, and three tests fail even when each class runs on its own.
Each test class guards
AppBuilder.Setupbehind its own class-local flag, butSetupis once-per-process — so the second class to run throws "Setup was already called". And desktopSetupWithoutStartingnever starts a dispatcher loop, so aDispatcher.UIThread.Invokefrom a test waits on a pump that will never run. That's the hang.The fix
Avalonia.Headless.XUnitexists for exactly this.[AvaloniaTestApplication]sets up one headless application per process, and[AvaloniaFact]runs a test on the headless dispatcher thread so UI work has somewhere to execute. Tests that touch controls or windows are marked[AvaloniaFact]; the rest stay plain[Fact]. The per-classEnsureAvaloniahelpers are no longer needed.It also removes the display requirement, so the suite can run in CI.
Measured on this branch
4af7ef2)Unrelated, but worth saying
Your reflective fallback in
AvaloniaAudioDrivers.Available()— dropping through toAudio.Driver.Driversinstead of hardcoding the driver list — is what let a macOS Core Audio backend slot in with oneProjectReferenceand no changes to your code at all. That design decision is why the port took days rather than weeks.Two more PRs to follow if you want them: the component library in the palette (closes the Phase 3 item at
GUI_PORT_PLAN.md:85— the ~87 parts inCircuit/Components/*.xmlare currently unreachable from the editor), and the live-path fixes from the remaining findings.🤖 Generated with Claude Code