So verwenden Sie Golden Master-Tests für Ihre iOS-Apps

Die menschliche Wahrnehmung ist ein interessantes Thema. Wir nehmen keine absoluten Werte wahr, sondern sehen die Dinge relativ. Überhaupt gewundert, warum Piraten Augenklappen hatten? Dies ist darauf zurückzuführen, dass das Auge unter dem Pflaster einen anderen relativen Wert zum Licht aufweist als das andere Auge. Als sie unter Deck gingen, konnten sie immer noch sehen und mussten ihre Sicht nicht einstellen. Das war vor langer Zeit lebensrettend. Es ist oft einfacher, Unterschiede zu erkennen, wenn Farben und Graustufen in relativen Werten wahrgenommen werden (z. B. ein Tiger im Dschungel). Leider macht es uns gleichzeitig anfällig für subtile Veränderungen. Wir sehen keine kleinen Änderungen, z. die Differenz zwischen 36 und 36,5% in einem Kreisdiagramm:

Glücklicherweise arbeitet der Computer mit absoluten Werten. Dies ermöglicht eine hohe Präzision und der obige Unterschied wäre ohne Probleme erkannt worden.

Während des Testens müssen wir häufig unsere aktuelle Version mit einer früheren Version vergleichen. Der sogenannte Golden Master-Test erfasst das Ergebnis eines Prozesses und vergleicht es mit einer früheren korrekten Version, um unerwartete Änderungen festzustellen. Eine übliche Implementierung dieses Ansatzes ist das Testen von Benutzeroberflächen-Snapshots. Aber irre dich nicht! Das Überprüfen Ihrer Back-End-APIs durch Vergleichen mit früheren Ergebnissen ist auch eine Form des Golden Master-Tests.

Da wir mit iOS-Apps arbeiten, werfen wir einen genaueren Blick auf das Testen von UI-Snapshots.

Gründe dafür

Golden Master-Tests werden Ihren Code nicht auf Korrektheit prüfen, aber Sie können sicher sein, dass das Verhalten dasselbe bleibt. Dies an sich kann wichtiger sein als die Korrektheit. Dies kann besonders nützlich sein, wenn Sie keine einfache Möglichkeit haben, eine andere Art von automatisierten Tests zu integrieren. Haben Sie jemals mit einer riesigen alten Codebasis gearbeitet? Ich hatte Glück und meine ersten beiden Jobs waren genau so. Jede Art von Test einzuführen war ein Schmerz. Es ist so weit gekommen, dass wir XCTest nicht in unsere iOS-App einführen konnten, da wir libstdc ++ verwendet haben. Eine Möglichkeit wäre gewesen, Golden Master-Tests hinzuzufügen. Zumindest hätten wir gewusst, ob wir etwas kaputt gemacht haben oder nicht. Leider wusste ich damals nichts von dieser Option.

Wenn Sie jedoch bereits über eine große Basis an Unit-Tests und UI-Tests verfügen, kann es Ihnen dennoch helfen, eine unerwartete Regression zu finden, die von Ihren Tests nicht abgedeckt wird (Sie können nicht jeden möglichen Pfad testen). Darüber hinaus kann die Analyse sehr detailliert sein. Es kann kleine Änderungen erkennen und ist sogar für den Fall geeignet, dass Ihr Code vom Ergebnis einer externen Bibliothek abhängt.

Wie bereits erwähnt, können Golden Master-Tests dazu beitragen, Wahrnehmungsunterschiede in unserer Benutzeroberfläche zu visualisieren.

UI-Snapshot-Test

Sehen wir uns die visuellen Wahrnehmungstests (auch als UI-Snapshot-Tests bezeichnet) genauer an.

Die Grundidee besteht darin, ein Bild des Bildschirms aufzunehmen, während die bekannten korrekten Daten angezeigt werden. Das ist unser goldener Meister. Jetzt erstellen wir jedes Mal, wenn wir unsere Software ändern, ein neues Bild desselben Bildschirms und vergleichen es mit unserem goldenen Meister. Falls alles gleich ist, wissen wir, dass wir keinen visuellen Unterschied haben. Wenn dies nicht der Fall ist, wissen wir, dass es einen Unterschied gibt, aber wie gehen wir vor? Dies bedeutet nicht unbedingt, dass wir Code beschädigt haben. Vielleicht enthält es erwartete Änderungen, vielleicht auch nicht. Wir wissen es nicht ohne zu schauen! Wir wissen nur, dass sich etwas geändert hat. Weitere Untersuchungen sind erforderlich, daher sind UI-Snapshot-Tests nicht unsere Antwort auf alle Fragen.

Testdaten

Ich habe einen kleinen Bildschirm erstellt, auf dem die deutsche Flagge als Kugel, zwei Beschriftungen, zwei Textansichten und eine Schaltfläche angezeigt wird.

Unser goldener Meister ist:

Dies ist das Ergebnis eines fehlgeschlagenen Tests:

Wie viele Unterschiede kann man finden, wenn man es nur ansieht?

PerceptualDiff

Google hat ein kleines Tool geschrieben, das den Unterschied zwischen zwei Bildern berechnet.

Hier ist die PerceptualDiff-Ausgabe unter Verwendung der beiden obigen Bilder:

FAIL: Bilder sind sichtbar anders
1839 Pixel sind unterschiedlich

Ich denke, Sie haben den Fehler im Benutzernamen gefunden, aber haben Sie den Unterschied auf der deutschen Flagge gesehen? Es war kein Quadrat mehr. Stattdessen waren es 127,5 x 128 Pixel. Diese Änderung ist fast unmöglich zu erkennen, wenn Sie mit bloßem Auge ein Bild verwenden, mit dem Sie vergleichen können. Standardmäßig wird keine Ausgabedatei generiert. Es gibt jedoch ein Ausgabe-Flag:

pdiff -output diff.ppm testimage.png goldenMaster.png

Dadurch wird eine Datei erstellt, in der Sie die Unterschiede visuell sehen können.

Ein nettes Merkmal, das Wahrnehmungsunterschiede aufweist, ist das Einstellen der Anzahl der erlaubten geänderten Pixel. Manchmal möchten Sie nicht, dass ein Test aufgrund kleiner Änderungen fehlschlägt, aber am häufigsten empfehle ich Ihnen, die Standardeinstellung beizubehalten.

Es gibt weitere Werkzeuge, um ein Diff für zwei Bilder zu erstellen. Mit ImageMagick können Sie dasselbe Diff-Ergebnis erzielen:

compare testimage.png goldenMaster.png -compose src diff.png

FBSnapshotTestCase

Sich hinzusetzen, Screenshots zu erstellen und diese dann zu vergleichen, ist natürlich eine ziemlich mühsame Aufgabe. Wir könnten dazu entweder einen Fastlane-Snapshot zum Erstellen der Snapshots verwenden (oder den neuen Feature-Snapshot von Xcode 9 verwenden), sie unter einem bestimmten Namen in einem Verzeichnis speichern und sie mit pdiff mit unserem Golden Master vergleichen.

Oder wir könnten FBSnapshotTestCase verwenden. Facebook hat dieses Tool veröffentlicht, um das Testen von Schnappschüssen in der iOS-Entwicklung zu vereinfachen. Im Folgenden werde ich untersuchen, wie man es einrichtet und wie man es benutzt. Ich werde seine Verwendung in Unit-Test-Zielen beschreiben, aber Sie können auch UI-Test-Ziele verwenden.

Konfiguration

Facebook beschreibt auf seiner Github-Seite, wie FBSnapshotTestCase über CocoaPods eingerichtet wird. Sie haben aber auch die Möglichkeit, es über Carthage zu integrieren. Es ist einfach wie jede andere Integration in Karthago.

Fügen Sie außerdem den Startparameter Ihres Schemas wie folgt hinzu, damit wir unsere goldenen Master-Images in unserem Repository finden können:

FB_REFERENCE_IMAGE_DIR: $ (SOURCE_ROOT) / $ (PROJECT_NAME) Tests / FailureDiffs
FB_REFERENCE_IMAGE_DIR: $ (SOURCE_ROOT) / $ (PROJECT_NAME) Tests

Erstellen Sie in unserem Unit-Test-Ziel eine neue Datei und ändern Sie den Import von XCTest in FBSnapshotTestCase. Machen Sie dasselbe für die Oberklasse Ihrer Testklasse.

Fügen Sie Ihrem TestCase einen Test wie diesen hinzu:

Dies bewirkt Folgendes:

  • Instanziiere einen ViewController
  • Starten Sie den Ansichtszyklus
  • Testdaten eingeben
  • Verwenden Sie FBSnapshotTest, um die Richtigkeit zu überprüfen

Um unseren goldenen Master zu erstellen, müssen wir recordMode = true zu setUp () hinzufügen. Wenn Sie diesen Test ausführen, schlägt er fehl. Aber wenn Sie ein wenig in die Protokolle lesen, heißt es:

fehlgeschlagen - Der Test wurde im Aufzeichnungsmodus ausgeführt. Das Referenzbild wird jetzt gespeichert. Deaktivieren Sie den Aufnahmemodus, um einen tatsächlichen Schnappschussvergleich durchzuführen!

Ihr goldener Master wurde in dem oben angegebenen Verzeichnis erstellt.

Wenn Sie recordMode = true entfernen, wird Ihr Test so konfiguriert, dass die Testdaten tatsächlich mit Ihrem Golden Master verglichen werden.

Lassen Sie uns sehen, was das Testergebnis für die oben aufgenommenen Bilder war.

In der Testausgabe finden Sie ein Verzeichnis, in dem Sie alle erstellten Bilder finden. Dieses enthält das testImage, das referenceImage und ein diffImage. Ich habe diese drei Bilder oben verwendet.

CI-Prozess

Leider kann FBSnapshotTestCase nicht beurteilen, ob dieser Fehler beabsichtigt ist oder nicht, sodass Sie mit Ausnahme von "Test fehlgeschlagen" keine Details erhalten. Dieses Urteil muss von Ihnen gemacht werden. Wir sind nicht die ersten, die sich mit visuellen Wahrnehmungstests befassen. Ein Team von Google hat dies getan und zum Glück haben sie ihren CI-Prozess in einem Video erwähnt. Im Allgemeinen sieht es so aus:

  1. Führen Sie Tests aus
  2. Erstellen Sie Bilder
  3. Bilder mit GM vergleichen
  4. Release Manager prüft, ob Änderungen erwartet wurden

Ich denke Punkt 4 ist der interessanteste. Bei jeder Änderung der Benutzeroberfläche überprüft Ihr Release Manager die fehlgeschlagenen Tests und entscheidet sich für oder gegen die Version. Sie betonen es auch:

"Fehlgeschlagene UI-Snapshot-Tests bedeuten nicht, dass etwas kaputt ist."

Fallstricke

Obwohl ich mich auf UI-Snapshot-Tests konzentrierte, erwähnte ich andere Anwendungsfälle für Golden Master-Tests. Beim Vergleich von Gleitkommawerten tritt ein Problem auf. Sie wissen, dass sie nicht mit Gleichberechtigung verglichen werden sollten, aber genau das macht der Golden Master-Test. Sie können dies also ausschließen oder spezielle Regeln festlegen. Ein weiteres Problem können Zeitstempel sein (z. B. das Ablaufdatum von Gutscheinen). Wenn Sie diese nicht kontrollieren können, können Sie sie ausschließen.

Fazit

Das Testen mit dem Goldenen Meister ist ein wirklich nützliches Werkzeug. Sie wissen, wenn etwas Unerwartetes auftritt, aber leider können Sie nicht immer wissen, was es war. Diese Art von Test kann problemlos zu jeder alten Codebasis hinzugefügt werden, auch wenn Sie aufgrund der hohen Komplexität nicht viele Komponententests schreiben können. Durch Ausführen dieser Tests wird sichergestellt, dass Sie nichts ändern. Die Bestätigung wird nicht überprüft. Stattdessen wird nach Änderungen gesucht. Auf diese Weise können Sie sicher sein, dass sich das Verhalten nicht geändert hat, wenn die Tests bestanden wurden.

Ich bin gespannt auf Ihre Erfahrungen mit Golden Master-Tests. Fühlen Sie sich frei, Ihren Fall in den Kommentaren unten zu teilen.

Weitere Lektüre

  • Snapshot-Test für Daten
  • Wie man keine GM-Tests schreibt