Xamarin / .NET MAUI Testing Guide (2026)
.NET MAUI (successor to Xamarin.Forms) brings cross-platform C# apps to iOS, Android, Windows, macOS. Testing them covers the shared logic in C#, platform-specific bindings, and the UI layer. This gui
.NET MAUI (successor to Xamarin.Forms) brings cross-platform C# apps to iOS, Android, Windows, macOS. Testing them covers the shared logic in C#, platform-specific bindings, and the UI layer. This guide is the 2026 approach.
The stack
- ViewModels and shared logic in C# — testable with xUnit / NUnit / MSTest
- XAML UI (optional) — snapshot or UI tested
- Platform-specific handlers — integration tests per platform
- Full app — Appium or MAUI test extensions
Unit tests
xUnit is the go-to:
public class LoginViewModelTests
{
[Fact]
public async Task Login_with_valid_creds_sets_authenticated()
{
var mockAuth = new Mock<IAuthService>();
mockAuth.Setup(a => a.Login(It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(AuthResult.Success);
var vm = new LoginViewModel(mockAuth.Object);
await vm.Login("test@example.com", "correct");
Assert.Equal(AuthState.Authenticated, vm.State);
}
}
Fast, deterministic, no UI required.
UI tests
Appium + UITest (Xamarin.UITest / Maui-specific)
[Test]
public void Login_happy_path()
{
app.WaitForElement(c => c.Marked("email"));
app.Tap(c => c.Marked("email"));
app.EnterText("test@example.com");
app.Tap(c => c.Marked("password"));
app.EnterText("correct");
app.Tap(c => c.Marked("sign_in"));
app.WaitForElement(c => c.Marked("home"));
}
AutomationId on XAML elements is the canonical locator:
<Button Text="Sign In" AutomationId="sign_in" Clicked="OnSignIn" />
Appium direct
var driver = new AndroidDriver(new Uri("http://localhost:4723"), options);
driver.FindElement(MobileBy.AccessibilityId("sign_in")).Click();
Portable test code across Android + iOS.
Snapshot tests
.NET MAUI has no first-class snapshot tool. Options:
- Take screenshot in UI test, compare to golden
- Third-party: MauiCommunityToolkit testing helpers
- Hand-roll with SkiaSharp rendering
Not as mature as iOS / Android native. Investment required.
Platform-specific
Handler tests: verify custom handler on Android behaves correctly vs iOS:
public class MyCustomHandler : ViewHandler<MyCustomView, PlatformViewType>
{
// Platform-specific wiring
}
Test with Xamarin.UITest or Appium on each platform — same test code, different build.
CI
# On each PR
- run: dotnet test --configuration Release
# Platform-specific UI tests
- run: dotnet test --configuration Release --filter Platform=Android
# requires Android SDK + emulator in CI
Gotchas
Binding errors silent
XAML binding typo does not throw; it silently shows nothing. Tests should assert expected values visible.
Lifecycle
OnAppearing / OnDisappearing ordering different from WPF / other XAML.
Async in ViewModel
Async void is common antipattern; use async Task and await properly in tests.
Different behavior across platforms
UI tests passing on Android do not mean iOS works. Run matrix.
How SUSA tests MAUI apps
SUSA drives MAUI apps via Android Accessibility (Android target) or Appium (iOS target). AutomationId maps to accessibility-id. Generated Appium scripts work for MAUI as for any other native app.
susatest-agent test mauiapp.apk --persona curious --steps 200
Best practices
- Shared logic in testable ViewModels. 80% of code is testable without UI.
- AutomationId on every interactive. Stable locators.
- UI tests for critical flows only. Slow and flakier.
- Run on both platforms. Parity is not automatic.
- Snapshot testing when time allows. Not mature, but worth investment.
MAUI testing is less mature than SwiftUI / Compose. The C# shared logic covers more than native frameworks would, offsetting somewhat. Focus on ViewModel tests; add UI tests for the critical 10%.
Test Your App Autonomously
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.
Try SUSA Free