EmuSen.LunaP.Testing 0.4.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package EmuSen.LunaP.Testing --version 0.4.0
                    
NuGet\Install-Package EmuSen.LunaP.Testing -Version 0.4.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EmuSen.LunaP.Testing" Version="0.4.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EmuSen.LunaP.Testing" Version="0.4.0" />
                    
Directory.Packages.props
<PackageReference Include="EmuSen.LunaP.Testing" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EmuSen.LunaP.Testing --version 0.4.0
                    
#r "nuget: EmuSen.LunaP.Testing, 0.4.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EmuSen.LunaP.Testing@0.4.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EmuSen.LunaP.Testing&version=0.4.0
                    
Install as a Cake Addin
#tool nuget:?package=EmuSen.LunaP.Testing&version=0.4.0
                    
Install as a Cake Tool

EmuSen.LunaP.Testing

The headless test harness LunaP tests itself with. Render capture, layout assertions and visual-tree queries for Avalonia windows, with no display and no GPU.

It is a separate package on purpose: EmuSen.LunaP references Avalonia and nothing else, and a harness needs xunit and Avalonia.Headless. Reference this from your test project only, and nothing your application ships gains a dependency.

dotnet add package EmuSen.LunaP.Testing

Using it

[assembly: AvaloniaTestApplication(typeof(TestAppBuilder))]
[assembly: CollectionBehavior(DisableTestParallelization = true)]

public class TestAppBuilder
{
    public static AppBuilder BuildAvaloniaApp() => LunaHeadless.BuildApp();
}

[Fact]
public Task The_settings_window_lays_out() => UiTest.Run(() =>
{
    var window = new SettingsWindow();
    window.Show();
    UiTest.AssertLaidOut(window, "settings");
});

LunaHeadless.BuildApp() builds the application with a real Skia render pass and LunaP's theme already included. That include is not cosmetic: without the real theme, templated controls have no template, render as nothing, and every assertion over them silently passes.

What it gives you

  • UiTest.Run(body) — dispatches onto the one headless UI thread the session owns. Window and control construction is only valid there.
  • UiTest.AssertLaidOut(window, name) — the assertion that earns its keep. A window that failed to lay out, or whose controls have no template, renders as one flat colour; counting distinct colours catches that where walking the logical tree does not.
  • UiTest.AssertStable(name, build) — renders twice and asserts the two are identical. A window showing a clock, a pid or a frame counter fails by design, which is what makes it a usable baseline target.
  • UiTest.Capture(window) → RGBA bytes, with Hash and DistinctColours.
  • VisualQuery — FindPart<T>(), FindParts<T>(), CountParts<T>(), FindNamed<T>(name). For windows built in code there is no XAML namescope for GetControl to search, so these go through the visual tree.

Set EMUSEN_UI_DUMP to a directory to get a PNG of every capture in the run. Pixel-exact baselines are opt-in behind EMUSEN_UI_BASELINE, because they are an artefact of one machine's font rendering.

Test parallelisation must be off

[assembly: CollectionBehavior(DisableTestParallelization = true)] is required, and the harness refuses to start without it rather than letting you find out later.

Every test shares one headless application, and several things around it are process-global — the settings store, the diagnostics hook, and the applied theme's resource dictionary. xunit parallelises across test classes, so one class's constructor can replace another class's state mid-assertion. It presents as a suite that is green on your machine and red on CI, which is exactly how it was found.

If your suite serialises another way — a single shared collection — say so explicitly with UiSession.ParallelismIsHandled = true.

Licence

GPL-3.0-or-later.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.10.0 122 8/19/2026
0.8.0 125 8/16/2026
0.7.0 122 8/13/2026
0.6.0 116 8/11/2026
0.5.0 112 8/10/2026
0.4.0 123 8/10/2026
0.3.0 119 8/10/2026