Property-basiertes Testen in Swift: Wenn normale Tests versagen
Haben Sie jemals einen Unit-Test geschrieben, der mit Bravour bestanden wurde, und dann stürzte die Anwendung mit echten Daten ab? Kommt Ihnen bekannt vor, oder? Klassische example-basierte Tests (bei denen wir eine bestimmte Eingabe und Ausgabe überprüfen) sind gut, aber sie haben einen grundlegenden Nachteil: Sie testen nur das, was wir uns selbst ausgedacht haben. Was aber, wenn der Bug an der Grenze der zulässigen Werte lebt oder in einer Kombination, die uns einfach nicht in den Sinn gekommen ist?
Hier kommt das property-basierte Testen in Swift ins Spiel. Es ist ein Ansatz, bei dem Sie nicht konkrete Fälle beschreiben, sondern Eigenschaften (Properties), die für beliebige Eingabedaten wahr sein müssen. Ein spezielles Framework (z. B. SwiftCheck) generiert hunderte von zufälligen Werten und prüft, ob Ihre Eigenschaft verletzt wird. Wenn ein Bug gefunden wird, "minimiert" das Framework die Eingabedaten – und Sie erhalten das einfachste Beispiel, bei dem alles kaputt geht.
In diesem Artikel werden wir uns ansehen, wie Sie property-basiertes Testen in Swift in Ihr Projekt integrieren, echte Codebeispiele schreiben und sehen, welche Bugs mit diesem Ansatz gefunden werden können. Los geht's!
Was ist property-basiertes Testen und warum wird es benötigt?
Stellen Sie sich vor, Sie testen eine Funktion, die ein Array sortiert. Anstatt 10 Tests mit verschiedenen Arrays zu schreiben, sagen Sie: "Für jedes Array ändert sich nach dem Sortieren die Länge nicht, und jedes Element ist kleiner oder gleich dem nächsten". Das ist eine Eigenschaft – eine Invariante, die erfüllt sein muss.
Property-basiertes Testen in Swift eignet sich ideal für:
- Überprüfung mathematischer Funktionen (Addition, Division, Rundung);
- Testen von Parsern und Serialisierern (Serialisierung → Deserialisierung sollte das Original zurückgeben);
- Überprüfung von Geschäftslogik mit vielen Kombinationen;
- Suche nach Regressionen an Grenzwerten.
Der Hauptvorteil: Sie finden Bugs, von deren Existenz Sie nicht einmal wussten. Und das ist, zugegeben, cooler, als das Offensichtliche zu bestätigen.
SwiftCheck – das wichtigste Werkzeug für property-basiertes Testen in Swift
In der Swift-Welt ist das beliebteste Framework für diesen Ansatz SwiftCheck. Es portiert Ideen aus Haskell (Bibliothek QuickCheck) und lässt sich hervorragend in XCTest integrieren.
Um zu beginnen, fügen Sie die Abhängigkeit in Ihre Package.swift ein:
// swift-tools-version:5.9import PackageDescription
let package = Package( name: "MyProject", dependencies: [ .package(url: "https://github.com/typelift/SwiftCheck.git", from: "0.12.0") ], targets: [ .testTarget( name: "MyProjectTests", dependencies: ["SwiftCheck"]), ])Jetzt können Sie Tests schreiben. Lassen Sie uns die grundlegende Syntax durchgehen.
Erster property-basierter Test: Überprüfung der Addition
Schreiben wir eine einfache Eigenschaft: "Addition ist assoziativ". Für beliebige ganze Zahlen sollte a + b + c gleich (a + b) + c sein.
import XCTestimport SwiftCheck
class MathPropertiesTests: XCTestCase { func testAdditionIsAssociative() { property("Addition ist assoziativ") <- forAll { (a: Int, b: Int, c: Int) in return (a + b) + c == a + (b + c) } }}Wir starten den Test – er führt 100 zufällige Kombinationen durch (standardmäßig). Wenn auch nur eine fehlschlägt, zeigt SwiftCheck die konkreten Werte an. Beachten Sie: Wir geben keine einzige konkrete Zahl an! Property-basiertes Testen in Swift generiert die Daten selbst.
Überprüfung der Rücktransformation (Roundtrip)
Dies ist das häufigste Muster. Angenommen, wir haben eine Struktur, die in JSON serialisiert wird. Eigenschaft: "Nach Serialisierung und Deserialisierung erhalten wir dasselbe Objekt zurück".