SmartUnitTests in Visual Studio 2015 – PEX is back

Schon mit Visual Studio konnte man Pex & Moles als AddOn installieren und verwenden (siehe: http://blog.ppedv.de/post/2011/01/12/Einfache-Stubs-fur-FileSystem-Aufrufe-beim-Unit-Testing-mit-Moles.aspx) Dieses, ursprünglich von MS Research entwickelte, Projekt bestand aus zwei Teilen. Moles ist ein Mocking Framework. Dieses hat unter dem Namen “Fakes-Framework” nun Einzug in Visual Studio 2012 gehalten (http://blog.ppedv.de/post/2012/07/22/Unit-Test-fur-SharePoint-Development-Fakes-Framework.aspx) Allerdings hat bis vor kurzem der zweite Teil gefehlt. PEX schaffte es nicht ins VS 2012 oder VS 2013. Nun mit der Preview von Visual Studio 2015 kommt nun kehrt das Tool “PEX” unter dem Namen “Smart Unit Tests” wieder zurück. Smart Unit Tests erstellen von einem bestehenden Code aus die dazu passenden Unit Tests. Es werden Parametrisierte Unit Tests angelegt.  Da der Code schon vorher bestehen muss, eignet sich dieses Tool nicht für Test Driven Development. In der Praxis werden aber die meisten Tests, wenn überhaupt, erst nach dem Code geschrieben. Und bei dieser Vorgangsweise kann das Tool sehr hilfreich sein. Nehmen wir für einen ersten Test eine ganz simple Funktion die in der Klasse “Berechnungen” implementiert wurde und schreiben für diese einen Unit Test: 1 public decimal Dividieren(int a, int b) 2 { 3 decimal erg = a / b; 4 return erg; 5 }   Im Visual Studio kann nun bei jeder Funktion im Kontext Menü der Punkt “Smart Unit Tests” aufgerufen werden. Das Projekt wird kompiliert und Visual Studio sucht nun für die Funktion jene Parameter, die es wert sind getestet zu werden. Die gefundenen Werte werden in einem eigenen Fenster ausgegeben: Gleichzeitig wurde im Projekt eine weitere Klasse angelegt. Diese nennt sich “BerechnungenTest” und enthält keine Testmethoden sondern PexMethoden. Die Methode die für die Tests der Dividieren-Funktion zuständig ist sieht so aus: 1 public partial class BerechnungenTest 2 { 3 [PexMethod] 4 [PexAllowedException(typeof(DivideByZeroException))] 5 public decimal Dividieren( 6 [PexAssumeUnderTest]Berechnungen target, 7 int a, 8 int b 9 ) 10 { 11 decimal result = target.Dividieren(a, b); 12 return result; 13 // TODO: add assertions to method BerechnungenTest.Dividieren(Berechnungen, Int32, Int32) 14 } 15 Diese Methode ist aber noch nicht die TestMethod die von MS Test ausgeführt wird. Die Testmethoden werden zunächst dynamisch erstellt. Im Smart Unit Test Fenster kann die erstellte Methode angesehen werden. Wenn eine Zeile im Fenster ausgewählt wird, erscheinen im rechten Teil die “Details” und hinter diesen sieht man die entsprechende Test-Methode: Diese Methode wurde dynamisch erstellt und ausgeführt. Möchte man diese als Test dauerhaft in das Projekt aufnehmen, muss aus dem Kontext-Menü der Punkt “Save” gewählt werden. Damit wird eine .g.cs Datei erstellt und diese enthält nun die Testmethode: 1 [TestMethod] 2 [PexGeneratedBy(typeof(BerechnungenTest))] 3 public void Dividieren598() 4 { 5 decimal d; 6 Berechnungen s0 = new Berechnungen(); 7 d = this.Dividieren(s0, 0, 1); 8 Assert.AreEqual<decimal>(default(decimal), d); 9 Assert.IsNotNull((object)s0); 10 } 11 } 12 } Die Einrückung der Klammern stimmt noch nicht ganz, aber das ist ja nur Formsache. Je komplexer der Code ist der getestet werden soll, umso umfangreicher werden die gefundenen Testfälle. Bei einer “erweiterten” Rechne-Methode werden es schon 7 Fälle. 1 public decimal Rechne(int a, int b, string rechenoperation) 2 { 3 decimal erg = 0; 4 switch (rechenoperation) 5 { 6 case "+": 7 erg = a + b; 8 break; 9 case "-": 10 erg = a - b; 11 break; 12 case "*": 13 erg = a * b; 14 break; 15 case "/": 16 erg = a / b; 17 break; 18 } 19 return erg; 20 }   Fazit um bestehenden Code einfach zu testen, ist dieses Tool perfekt. Es ermittelt zuverlässig die “interessanten” Parameter der Funktionen. Allerdings widerspricht das komplett dem Test-First-Ansatz. Aber zumindest sind ein paar Tests besser, als gar keine Tests. Und dieses Tool, erleichtert das Erstellen der Unit Tests ungemein.