31 März 2015

Von MSTest nach xUnit.net

Das in Visual Studio integrierte Testframework von Microsoft verwende ich nun bereits seit zig Jahren – wenn ich mich richtig erinnere seit Visual Studio 2008. Im Grunde war ich meistens auch zufrieden damit. Performance war jetzt nicht schön, aber für meine Anwendungsfälle auch kein Problem. In den letzten Wochen/Monaten habe ich mich aber dazu entschlossen, nun endgültig auf xUnit umzusteigen. Warum? Das offensichtliche ist schon mal, dass von offizieller Seite nix mehr bei MSTest passiert. Weiterhin wird die Performance bei der steigenden Anzahl meiner automatischen Tests immer mehr zum Problem. Die Möglichkeit zur Parametrierung von Testfällen ist für mich kein Must-Have, aber auch dieses Feature macht xUnit schon interessant. Gestern und heute habe ich die Umstellung entsprechend gemacht und bin überrascht, wie wenig Arbeit das letzten Endes gemacht hat.

Bevor ich genauer auf xUnit eingehe, möchte ich kurz beschreiben, wie ich vorher automatisierte Tests geschrieben und verwendet habe. Bei MSTest haben sich bei mir ein paar kleine Regeln entwickelt, welche man am Projekt Seeing# [1] gut sehen kann. Zunächst definiere ich für jede Test-Klasse eine Kategorie, welche per Attribut auch bei jeder in derselben Klasse definierten Testmethode ran gehängt wird. Ergebnis ist eine sauber kategorisierte Testliste wie in Abbildung 1 zu sehen.

UnitTests
Abbildung 1: Testexplorer mit MSTest

So weit, so klar. Die Testmethoden programmiere ich entsprechend wie bei automatisierten Tests üblich aus. An einigen Stellen, vor allem im Zusammenhang mit 3D-Rendering, verwende ich in den Testmethoden auch async-await, was in MSTest auch super funktioniert.

Nun zu xUnit.net: Mein Wissen über das Framework habe ich entsprechend von einigen Usergroup-Vorträgen wie z. B. von Kenny Pflug in Regensburg [2]. Weiterhin waren hier auch Pluralsight [3] und das entsprechende Git-Repository von xUnit [4] super Quellen. Mein erster Schritt war nun, die Verweise auf die MSTest-Assemblie aus den Testprojekten zu verbannen und stattdessen per Nuget die Pakete für xUnit zu installieren (Siehe Abbildung 2). Wichtig an der Stelle ist, dass nichts installiert werden muss. Dem Testrunner von Visual Studio reicht es, wenn xUnit als Verweis im Testprojekt hinzugefügt wird.

Nuget Pakete für XUnit.Net
Abbildung 2: Nuget Pakete für XUnit.Net

Um nun eine ähnliche Kategorisierung zu erreichen, wie ich es unter MSTest hatte, genügen bei mir die Standard-Attribute von xUnit. Nachfolgendes C#-Coding zeigt die gleiche Stelle, wie die MSTest-Variante oben, nur per xUnit.net. Das coole: Mit dem Trait-Attribut hier wird fast das Gleiche erreicht, wie mit dem TestCategory Attribut von MSTest.

Neben der Anpassung der Attribute musste ich auch die Assert-Aufrufe anpassen. Letzten Endes waren das aber Kleinigkeiten, da es dann z. B. anstelle von Assert.IsTrue einfach nur Assert.True heißt. Ein paar Mal Suchen und Ersetzen und dann ist die Sache auch erledigt.

Ein paar Probleme hatte ich dann aber doch:

  • xUnit.net setzt anders als MSTest ein SynchronizationContext ein. Da meine Tests zum Teil davon ausgingen, dass kein SynchronizationContext gesetzt ist, führte dieses Thema bei einigen Tests entsprechend zu Deadlocks.
  • xUnit.net kann Tests parallel ausführen. Standardmäßig werden alle Methoden innerhalb einer Testklasse sequenziell nacheinander ausgeführt, parallel dazu aber die Methoden in anderen Testklassen. Grundsätzlich zwar ein gutes Feature, gerade bei meinen 3D-Rendering Themen führte das aber zu Problemen, da die 3D-Engine auf einige Singletons setzt und die Testmethoden am Ende immer prüfen, ob alle Ressourcen darin ordentlich aufgeräumt wurden. Wenn jetzt gerade ein anderer Test parallel läuft und Ressourcen belegt, dann geht der Test trotz Erfolg auf Fehler. Lösung: Parallelisierung kann man anders einstellen, ich habe etwa das Collection Attribut verwendet, um mehrere Testklassen zu einer Collection zusammenzufassen und habe damit eine Parallelisierung der Methoden über diese Klassen vermeidet.
  • Etwas nervig war anfangs, dass xUnit als Namen der Testmethoden im Testexplorer standardmäßig auch kompletten Namespace- und Klassennamen mit anzeigt. Hier hat aber ein Konfigurationsflag in der app.config der Test-Assembly gereicht.

Der aktuelle Stand der Testautomatisierung von Seeing# kann jederzeit im Git-Repository abgerufen werden. Einfach rein schauen..

Verweise:
[1] https://github.com/RolandKoenig/SeeingSharp
[2] http://www.it-speicher.de/kompetenz/121632-521,1,0.html
[3] http://www.pluralsight.com/courses/xunitdotnet-test-framework
[4] https://github.com/xunit/xunit


Schlagwörter: , ,
Copyright 2019. All rights reserved.

Verfasst 31. März 2015 von Roland in category "Allgemeines

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.