Перейти к основному содержимому

Headless Testing with XUnit

Preparation​

This page assumes that XUnit project was already created. If not, please follow XUnit "Getting Started" and "Installation" here https://xunit.net/docs/getting-started/netfx/visual-studio.

Install packages​

Aside from XUnit packages, we need to install two more packages:

подсказка

Headless platform doesn't require any specific theme, and it is possible to swap FluentTheme with any other.

Setup Application​

As in any other Avalonia app, an Application instance needs to be created, and themes need to be applied. When using the Headless platform, the setup is not much different from a regular Avalonia app and can mostly be reused.

<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Tests.App">
<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>

And the code:

using Avalonia;
using Avalonia.Headless;

public class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
}
примечание

Usually, the BuildAvaloniaApp method is defined in the Program.cs file, but NUnit/XUnit tests don't have it, so it is defined in the App file instead.

Initialize XUnit Tests​

The [AvaloniaTestApplication] attribute wires the tests in the current project with the specific application. It needs to be defined once per project in any file.

[assembly: AvaloniaTestApplication(typeof(TestAppBuilder))]

public class TestAppBuilder
{
public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure<App>()
.UseHeadless(new AvaloniaHeadlessPlatformOptions());
}

Test Example​

[AvaloniaFact]
public void Should_Type_Text_Into_TextBox()
{
// Setup controls:
var textBox = new TextBox();
var window = new Window { Content = textBox };

// Open window:
window.Show();

// Focus text box:
textBox.Focus();

// Simulate text input:
window.KeyTextInput("Hello World");

// Assert:
Assert.Equal("Hello World", textBox.Text);
}

Instead of the typical [Fact] attribute, we need to use [AvaloniaFact] as it sets up the UI thread. Similarly, instead of [Theory], there is a [AvaloniaTheory] attribute.