xaml-csharp-development-skill-for-avalonia

Testing Stack: Headless, Render, and UI Tests

Table of Contents

  1. Scope and APIs
  2. Test Runtime Architecture
  3. Authoring Patterns
  4. AOT-Safe Testing Guidance
  5. Troubleshooting

Scope and APIs

Primary APIs:

Important members:

Reference source files:

Test Runtime Architecture

Headless test pipeline:

  1. Build app with UseHeadless(...).
  2. Run tests on UI dispatcher via headless test framework attributes/session.
  3. Drive input via HeadlessWindowExtensions methods.
  4. Force rendering and capture frames for snapshot/visual assertions.

Authoring Patterns

Headless app setup

public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure<TestApp>()
    .UseSkia()
    .UseHeadless(new AvaloniaHeadlessPlatformOptions
    {
        UseHeadlessDrawing = false
    });

Assembly-level test runtime configuration

using Avalonia.Headless;

[assembly: AvaloniaTestApplication(typeof(TestApp))]
[assembly: AvaloniaTestIsolation(AvaloniaTestIsolationLevel.PerTest)]

xUnit UI test

using Avalonia.Controls;
using Avalonia.Headless.XUnit;

public class UiTests
{
    [AvaloniaFact]
    public void Can_render_window_frame()
    {
        var window = new Window { Width = 400, Height = 300 };
        window.Show();

        var frame = window.CaptureRenderedFrame();
        if (frame is null)
            throw new Exception("Expected rendered frame.");
    }
}

Deterministic input simulation

window.MouseMove(new Point(50, 20));
window.MouseDown(new Point(50, 20), Avalonia.Input.MouseButton.Left);
window.MouseUp(new Point(50, 20), Avalonia.Input.MouseButton.Left);
window.KeyTextInput("abc");

AOT-Safe Testing Guidance

Troubleshooting

  1. GetLastRenderedFrame() throws:
    • Headless app is using headless drawing backend; switch to Skia + UseHeadlessDrawing = false.
  2. Flaky async UI assertions:
    • Run assertions through test dispatcher (AvaloniaFact / AvaloniaTest / session Dispatch).
  3. Input appears ignored:
    • Window/top-level not shown or no focused target.
    • Missing render/job stabilization before assertion.
  4. State leaks between tests:
    • Use AvaloniaTestIsolationLevel.PerTest for strict isolation.

XAML-First and Code-Only Usage

Default mode:

XAML-first references:

XAML-first usage example:

<UserControl xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:vm="using:MyApp.ViewModels"
             x:Class="MyApp.Views.TestView"
             x:DataType="vm:TestViewModel">
  <TextBlock Text="{CompiledBinding Status}" />
</UserControl>

Code-only alternative (on request):

var window = new Window
{
    Content = new TextBlock { Text = "Smoke test" }
};
window.Show();