Ihr Unit-Test lügt (und Sie wissen es)
\n\nStellen Sie sich vor: Sie haben 50 Unit-Tests geschrieben, alle grün, Abdeckung 90%. Sie sind zufrieden. Aber eine Woche später fällt die Produktion aus. Es stellt sich heraus, dass Ihre Methode SortArray() hervorragend für [1, 2, 3] und [3, 1, 2] funktioniert, aber bei [int.MaxValue, -1, 0] versagt. Kommt Ihnen das bekannt vor?
Das Problem klassischer Unit-Tests ist die Voreingenommenheit des Entwicklers. Sie schreiben Tests für die Daten, die Sie erwarten. Hacker, echte Benutzer und zufällige Randbedingungen folgen anderen Regeln.
\n\nHier kommt das Property-basierte Testen in C# (oder eigenschaftsbasiertes Testen) ins Spiel. Anstatt zu überprüfen „wenn A, dann B", beschreiben Sie Eigenschaften, die immer wahr sein müssen. Und das Framework generiert selbstständig hunderte zufällige Eingabedaten und überprüft Ihre Behauptungen.
\n\nIn diesem Artikel werden wir untersuchen, wie Sie Property-basiertes Testen in C# mit der Bibliothek FsCheck einführen, echte Beispiele schreiben und sehen, wie es Bugs fängt, die normale Tests übersehen.
\n\nWas ist Property-basiertes Testen?
\n\nProperty-basiertes Testen ist ein Ansatz, bei dem Sie Invarianten (Eigenschaften) Ihres Programms formulieren. Zum Beispiel:
\n- \n
- „Nach dem Sortieren ändert sich die Länge des Arrays nicht" \n
- „Die umgekehrte Reihenfolge einer Zeichenkette ergibt die ursprüngliche Zeichenkette" \n
- „Die Summe zweier positiver Zahlen ist immer positiv" \n
Das Framework (z.B. FsCheck) generiert Dutzende und Hunderte zufälliger Eingabedaten und überprüft, dass die Eigenschaft für alle gilt. Wird ein Gegenbeispiel gefunden – fällt der Test, und Sie erhalten die konkreten Werte, die den Code zum Scheitern gebracht haben.
\n\nIm Gegensatz zu Unit-Tests schreiben Sie nicht Assert.AreEqual(3, Add(1,2)). Sie schreiben Assert(x + y == y + x) – und testen die Kommutativität für tausende Zahlenpaare.
Unterschied zu gewöhnlichen Unit-Tests
\n\n| Unit-Tests | Property-basierte Tests |
|---|---|
| Überprüfen konkrete Beispiele | Überprüfen allgemeine Gesetze |
| Daten werden vom Entwickler vorgegeben | Daten werden vom Framework generiert |
| Übersehen Randfälle | Erkunden automatisch Grenzen |
| Leicht zu lesen | Erfordern abstraktes Denken |
Die Bibliothek FsCheck: Ihr wichtigstes Werkzeug
\n\nIn der C#-Welt ist FsCheck (ursprünglich ein Port der Haskell-Bibliothek QuickCheck) der De-facto-Standard für Property-basiertes Testen. Es integriert sich mit xUnit, NUnit und MSTest.
\n\nDie Installation ist einfach:
\ndotnet add package FsCheck\ndotnet add package FsCheck.Xunit // für die Integration mit xUnit\n\nFsCheck kann zufällige Daten für primitive Typen (int, string, float), Listen, Arrays, Tupel und sogar benutzerdefinierte Typen (über benutzerdefinierte Generatoren) generieren.
Unser ersten Property-basierten Test in C# schreiben
\n\nBeginnen wir einfach: Wir überprüfen, dass die Addition ganzer Zahlen kommutativ ist.
\n\nusing FsCheck;\nusing FsCheck.Xunit;\n\npublic class AdditionTests\n{\n [Property]\n public bool Commutative_Addition(int x, int y)\n {\n return x + y == y + x;\n }\n}\n\nFühren Sie den Test aus. FsCheck generiert 100 zufällige int-Paare (standardmäßig) und überprüft die Eigenschaft. Wenn kein Gegenbeispiel gefunden wird – ist der Test grün. Wenn wir einen Fehler gemacht hätten (z.B. x - y == y - x geschrieben), würde der Test mit einem konkreten Beispiel fehlschlagen: (5, 3) – weil 5 - 3 != 3 - 5.
Den Code analysieren
\n- \n
- [Property] – ein Attribut, das FsCheck mitteilt, dass dies ein Property-basierter Test ist. \n
- Die Methode gibt
boolzurück – wenn siefalsezurückgibt, schlägt der Test fehl. \n - Parameter
int x, int y– FsCheck wird automatisch zufällige Werte einsetzen.