Skip to content
Back to skills

Avalonia Testing

ASecurity

Use when writing tests for Avalonia apps — headless UI testing, ViewModel unit tests, UI automation, or setting up the Avalonia test infrastructure.

  • 37 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 10, 2026
testingc#testing

Works with

  • cli

Security analysis

A100/100

Scanned September 10, 2026

npx -y skills add linuxdevel/Avalonia-skills --skill avalonia-testing --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Avalonia Testing?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Avalonia Testing
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/linuxdevel-avalonia-testing/badge)](https://www.skillsdirectory.com/skills/linuxdevel-avalonia-testing)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: avalonia-testing
description: Use when writing tests for Avalonia apps — headless UI testing, ViewModel unit tests, UI automation, or setting up the Avalonia test infrastructure.
---
# Avalonia Testing

## Overview
Two testing approaches: ViewModel unit tests (no Avalonia needed, plain xUnit/NUnit), and headless UI tests using `Avalonia.Headless` (renders without a display).

## ViewModel Unit Tests (No UI)
No special setup needed — ViewModels are plain C# classes:
```csharp
[Fact]
public void Name_Change_RaisesPropertyChanged()
{
    var vm = new MainViewModel();
    var raised = new List<string?>();
    vm.PropertyChanged += (_, e) => raised.Add(e.PropertyName);

    vm.Name = "Alice";

    Assert.Contains(nameof(vm.Name), raised);
    Assert.Equal("Alice", vm.Name);
}

[Fact]
public async Task SaveCommand_WhenNameEmpty_CannotExecute()
{
    var vm = new MainViewModel { Name = "" };
    Assert.False(vm.SaveCommand.CanExecute(null));
}
```

## Headless Testing Setup
NuGet packages:
- `Avalonia.Headless`
- `Avalonia.Headless.XUnit` (or `.NUnit`)

```csharp
// Assembly-level attribute (AssemblyInfo.cs or top of test file)
[assembly: AvaloniaTestApplication(typeof(TestAppBuilder))]

public class TestAppBuilder
{
    public static AppBuilder BuildAvaloniaApp()
        => AppBuilder.Configure<App>()
            .UseHeadless(new AvaloniaHeadlessOptions { UseHeadlessDrawing = true });
}
```

## Writing Headless Tests (xUnit)
```csharp
public class MainWindowTests
{
    [AvaloniaFact]
    public void Button_Click_UpdatesViewModel()
    {
        var window = new MainWindow();
        var vm = new MainViewModel();
        window.DataContext = vm;
        window.Show();

        var button = window.FindControl<Button>("SaveButton")!;
        button.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));

        Assert.True(vm.SaveWasCalled);
    }

    [AvaloniaFact]
    public async Task TextBox_Input_UpdatesBinding()
    {
        var window = new MainWindow();
        window.DataContext = new MainViewModel();
        window.Show();

        var textBox = window.FindControl<TextBox>("NameBox")!;
        textBox.RaiseTextInput("Hello");

        await Task.Delay(50); // allow binding to propagate
        Assert.Equal("Hello", ((MainViewModel)window.DataContext!).Name);
    }
}
```

## Finding Controls
```csharp
// By name (x:Name)
var btn = window.FindControl<Button>("MyButton");

// By type (first match)
var textBox = window.FindDescendantOfType<TextBox>();

// All of type
var allButtons = window.GetVisualDescendants().OfType<Button>();
```

## Simulating Input
```csharp
// Keyboard
window.KeyPress(Key.Enter, KeyModifiers.None);
window.KeyTextInput("Hello");

// Mouse/Pointer
window.MouseDown(new Point(100, 50), MouseButton.Left);
window.MouseMove(new Point(150, 50));
window.MouseUp(new Point(150, 50), MouseButton.Left);
```

## Screenshot Testing
```csharp
[AvaloniaFact]
public void Window_RendersCorrectly()
{
    var window = new MainWindow();
    window.Show();

    // Capture frame as bitmap
    var bitmap = window.CaptureRenderedFrame()!;
    // Compare or save for regression
    bitmap.Save("snapshot.png");
}
```

## Testing with NUnit
```csharp
[TestFixture]
public class Tests
{
    [AvaloniaTest]  // instead of [Test]
    public void MyTest() { }
}
```

## Community Testing Libraries

| Library | NuGet | Purpose |
|---|---|---|
| Verify.Avalonia | `Verify.Avalonia` | Extends Verify for snapshot/approval testing of Avalonia UI |

### Snapshot Testing with Verify.Avalonia
```csharp
[AvaloniaFact]
public async Task Window_MatchesSnapshot()
{
    var window = new MainWindow();
    window.Show();

    await Verify(window); // saves .verified.png on first run, diffs on subsequent
}
```
Requires: `Verify.Avalonia` + `Verify.Xunit` (or NUnit variant).
On first run, creates a `.verified.png` baseline. Subsequent runs diff against it — fails on visual regression.

## Common Mistakes
- Missing `[assembly: AvaloniaTestApplication]` — headless renderer not initialized, NullReferenceException
- Using `[Fact]` instead of `[AvaloniaFact]` for UI tests — no Avalonia dispatcher, random failures
- Forgetting `window.Show()` before interacting — controls not attached to visual tree
- Testing bindings synchronously — bindings may be async, add small delay or use `Dispatcher.UIThread.RunJobs()`

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.