Unit Testing einer Xamarin.Forms App

In diesem Beitrag möchte ich euch zeigen, wie ihr in eure bestehende Xamarin.Forms App Unit Tests hinzufügen könnt. Damit habt ihr die Möglichkeit die Businesslogik durch zahlreiche Tests zu validieren und so frühzeitig Fehler in eurem Code zu finden. Ausgangslage bildet die kleine App MyAwesomeApp, welche einen Logik-Mechanismus bereitstellt. Nach der Eingabe von Nutzernamen und Passwort kann man auf den Login-Button klicken und gelangt entweder zur Hauptseite oder bleibt auf der Login-Seite.

Damit ihr zusammen mit mir programmieren könnt, könnt ihr euch den Sourcecode durch einen Klick auf den Button herunterladen.

Zunächst müssen wir der bestehenden Solution ein neues Projekt hinzufügen. Dafür klicken wir mit der rechten Maustaste auf Solution 'MyAwesomeApp' und wählen den Eintrag Add > New Project aus. Im Suchfeld geben wir NUnit 3 Test Project ein und wählen die entsprechende Vorlage aus.

XF - Unit Tests

Im nächsten Schritt müssen wir einen Namen für das Projekt angeben. Ich wähle hier MyAwesomeApp.Tests, denn dies ist ein gewisser Standard. Im nächsten Schritt wählen wir das Framework aus, ich verwende hier .NET Core 3.1 (Long-term support). Anschließend wird das Projekt angelegt. Wir löschen zunächst die Datei UnitTest1.cs, da wir diese Datei nicht benötigen.

Nun müssen wir eine Referenz zu unserer Xamarin.Forms dem Test-Projekt hinzufügen. Dafür klicken wir mit der rechten Maustaste auf Dependencies und wählen Add Project Reference aus. Anschließend setzen wir den Haken bei MyAwesomeApp und bestätigen mit Ok.

XF - Unit Tests

Nun erstellen wir einen neuen Ordner Services und darin eine neue Klasse mit dem Namen LoginServiceTests. Nun fügen wir eine private Variable hinzu, um eine Referenz auf den LoginService zu erhalten.

private ILoginService _loginService;

Wir erstellen nun eine Methode Init, welche eine Instanz des LoginServices für uns erstellt und der gerade hinzugefügten Variable zuweist. Außerdem markieren wir die Methode mit dem Attribute SetUp, so dass diese Methode vor jedem einzelnen Test aufgerufen wird und wir dadurch eine neue Instanz des Services erhalten.

[SetUp]
public void Init()
{
    _loginService = new LoginService(httpMock.Object);
}

Nun wollen wir zwei Tests schreiben. Zum einen einen Test mit validen Nutzerdaten, wo wir am Ende erwarten, dass der Login erfolgreich ist und zum anderen ein Test mit invaliden Nutzerdaten, wo am Ende der Login nicht erfolgreich ist. Der Aufbau für so einen Test folgt immer dem gleichen Schema: ArrangeActAssert. Zunächst wird der Test vorbereitet, in unserem Fall gegeben wir den Nutzernamen und das Passwort an. Im zweiten Schritt wird die Methode aufgerufen, welche getestet werden soll. Im dritten und letzten Abschnitt werden dann die Annahmen überprüft. In unserem Fall ist dies nur ein einzelnes Assert, da wir nur auf true bzw. false überprüfen. Aber hier können beliebig viele Dinge überprüft werden. Zu guter Letzt muss noch die Methode mit dem Test-Attribut versehen werden.

[Test]
public async Task TestLoginWithValidCredentialsAsync()
{
    // arrange
    var username = "test";
    var password = "test";

    // act
    var result = await _loginService.LoginAsync(username, password);

    // assert
    Assert.IsTrue(result);
}

[Test]
public async Task TestLoginWithInvalidCredentialsAsync()
{
    // arrange
    var username = "test";
    var password = "test21";

    // act
    var result = await _loginService.LoginAsync(username, password);

    // assert
    Assert.IsFalse(result);
}

Da der LoginService zum jetzigen Zeitpunkt nicht sehr komplex ist, sind dies bereits alle Tests für diesen. Daher wollen wir uns jetzt anschauen, wie wir die Tests ausführen können. Dazu wählen wir Test > TestExplorer. Hier sollten nach kurzer Zeit die beiden von uns angelegten Tests erscheinen. Wenn dies nicht der Fall ist, dann fehlt gegebenenfalls das Test-Attribut. Ansonsten einfach einmal das Projekt bauen und dann sollten die Tests sichtbar sein.

XF - Unit Tests

Über den Play-Button lassen sich die Tests nun ausführen. Der erste Test-Lauf nimmt ein paar Minuten in Anspruch, da zunächst die ganzen Projekte gebaut werden müssen. Die weiteren Test-Läufe sind dann deutlich schneller.

XF - Unit Tests

Wie wir sehen können, sind die beiden Tests erfolgreich. Wir können nun einen Test machen und in der Methode TestLoginWithValidCredentialsAsync geben wir ein anderes Passwort an, so dass die Validierung fehlschlagen muss. Wenn wir nun den Test wiederholen, dann sehen wir, dass der Test fehlschlägt.

XF - Unit Tests

Wir passen nun den Test wieder an, so dass dieser wieder erfolgreich ist.

Damit haben wir die ersten Unit Tests für unseren LoginService geschrieben und erfolgreich ausgeführt. Nun besteht die Möglichkeit dieses Tests zum Beispiel im Rahmen einer Build-Pipeline laufen zu lassen. So kann man sicherstellen, dass durch Anpassungen des LoginServices die eigentliche Logik nicht verändert und fehlerhaft wird.

Das fertigen Projekt könnt ihr euch über den folgenden Button herunterladen.

BindableLayout: Ersatz für die RepeaterView NuGet: Xamarin Community Toolkit Auf plattformspezifische APIs in einer Xamarin.Forms-App zugreifen