MainWindowViewTests kept failing on CI in Test Case Cleanup ('The calling
thread cannot access this object') while passing 56/56 locally. The cause was
delivery, not the fix: xunit.runner.json only takes effect if it is copied
beside the test DLL, and under CI's 'dotnet build' + 'dotnet test --no-build'
split it did not arrive, so CI ran with parallel collections while local runs
did not.
[assembly: CollectionBehavior(DisableTestParallelization = true)] is compiled
into the DLL and cannot fail to deploy. It lives beside the existing
AvaloniaTestApplication/AvaloniaTestIsolation attributes, which document the
same thread-affinity hazard. The json and its csproj copy rule are removed so
there is one source of truth.
36 lines
1.7 KiB
C#
36 lines
1.7 KiB
C#
using Avalonia;
|
|
using Avalonia.Headless;
|
|
using Xunit;
|
|
|
|
[assembly: AvaloniaTestApplication(typeof(AcDream.Launcher.Tests.TestAppBuilder))]
|
|
[assembly: AvaloniaTestIsolation(AvaloniaTestIsolationLevel.PerAssembly)]
|
|
|
|
// Compiled INTO the assembly on purpose. A xunit.runner.json expresses the same
|
|
// intent but only works if the file is copied beside the test DLL; under CI's
|
|
// `dotnet build` + `dotnet test --no-build` split it did not arrive, so the
|
|
// suite ran with parallel collections and MainWindowViewTests failed in Test
|
|
// Case Cleanup ("The calling thread cannot access this object") while passing
|
|
// locally. An assembly attribute cannot fail to deploy.
|
|
[assembly: CollectionBehavior(DisableTestParallelization = true)]
|
|
|
|
namespace AcDream.Launcher.Tests;
|
|
|
|
/// <summary>
|
|
/// Headless Avalonia application entry point for <c>[AvaloniaFact]</c>/
|
|
/// <c>[AvaloniaTheory]</c> tests (see #399). Reuses the launcher's real
|
|
/// <see cref="App"/> so the FluentTheme styles declared in App.axaml are
|
|
/// live for every test — <see cref="MainWindow"/>'s controls (TreeView,
|
|
/// Button, TextBox, ...) need a real control theme to template and focus
|
|
/// correctly, not just an unstyled visual tree.
|
|
/// The assembly contains one Avalonia test that owns the complete window
|
|
/// matrix. Keep one application/dispatcher for that process: Avalonia 12's
|
|
/// per-test teardown can recreate the compositor after its render loop has
|
|
/// become owned by a different worker, producing a thread-affinity cleanup
|
|
/// failure after an otherwise passing test.
|
|
/// </summary>
|
|
public static class TestAppBuilder
|
|
{
|
|
public static AppBuilder BuildAvaloniaApp() =>
|
|
AppBuilder.Configure<App>()
|
|
.UseHeadless(new AvaloniaHeadlessPlatformOptions());
|
|
}
|