Einführung in iOS-Tests mit UI Automation
Stellen Sie sich vor, Sie könnten Skripte schreiben, die automatisch mit Ihrer iOS-Anwendung interagieren und die Ergebnisse überprüfen. Mit UI Automation können Sie das. UI Automation ist ein von Apple bereitgestelltes Tool, mit dem Sie Ihre iOS-Anwendung auf einer höheren Ebene testen können als mit XCTest.
1. White Box versus Black Box Testing
Sie haben vielleicht schon einmal den Vergleich zwischen White Box Testing und Black Box Testing gehört, wenn es darum geht, wie man eine Software testen kann. Wenn Sie mit diesen Konzepten nicht vertraut sind, möchte ich Ihnen erklären, wie sie funktionieren.
White Box Testing
Stellen Sie sich vor, dass ein Stück Software in einer Box läuft. Mit White-Box-Tests kann man in die Box hineinschauen und sich alle Details der Software ansehen, um dann fundierte Entscheidungen zu treffen, wie man die Software testen kann. Mit den von Ihnen geschriebenen Tests können Sie auch tiefere Einblicke in die Software erhalten.
Unit-Tests sind White-Box-Tests. Beim Schreiben von Unit-Tests hat der Tester feinkörnigen Zugriff auf den zu testenden Code. Der Tester kann Tests schreiben, die die zu testende Software auf Methoden- oder Einheitsebene nutzen.
In der iOS-Softwareentwicklung verwenden wir das XCTest-Framework, um diese Art von Tests durchzuführen. Werfen Sie einen Blick auf ein anderes Tutorial, das ich über die ersten Schritte mit XCTest geschrieben habe.
Black Box Testing
Beim Black Box Testing ist die Box undurchsichtig. Der Tester kann nicht in das Innere der Box sehen. Der Tester kann nicht auf die Implementierung der Codebasis zugreifen und weiß nichts über diese, um Tests zu schreiben. Stattdessen ist der Tester gezwungen, die Anwendung wie ein Endbenutzer zu benutzen, indem er mit der Anwendung interagiert und auf ihre Antwort wartet, um die Ergebnisse zu überprüfen.
Es gibt mindestens zwei Möglichkeiten, diese Art von Tests durchzuführen.
- Ein Tester, der wiederholt und manuell eine Reihe von vordefinierten Schritten durchführt und die Ergebnisse visuell überprüft.
- Spezialisierte Tools verwenden, um die Anwendung mit APIs zu testen, die sich ähnlich verhalten, wie ein Mensch interagiert.
In der iOS-Anwendungsentwicklung stellt Apple ein Tool namens UI Automation zur Verfügung, um Blackbox-Tests durchzuführen.
2. Was ist UI Automation?
UI Automation ist ein Tool, das Apple für automatisierte Tests auf höherer Ebene von iOS-Anwendungen bereitstellt und pflegt. Die Tests werden in JavaScript geschrieben und richten sich nach einer von Apple definierten API.
Das Schreiben von Tests kann durch die Verwendung von Barrierefreiheitskennzeichnungen für Elemente der Benutzeroberfläche in Ihrer Anwendung erleichtert werden. Aber keine Sorge, wenn Sie diese nicht definiert haben, gibt es Alternativen.
Der UI Automation API fehlt das typische xUnit-basierte Format zum Schreiben von Tests. Ein Unterschied zu Unit-Tests besteht darin, dass der Tester Erfolg und Misserfolg manuell protokollieren muss. UI-Automatisierungstests werden über das Automatisierungsinstrument innerhalb des Instruments ausgeführt, das mit den Entwicklerwerkzeugen von Apple geliefert wird. Die Tests können im iOS-Simulator oder auf einem physischen Gerät ausgeführt werden.
3. Schreiben von UI-Automatisierungstests
Schritt 1: Öffnen des Beispielprojekts
Ich habe das Beispielprojekt, das im vorherigen Tutorial über iOS-Tests verwendet wurde, mit einigen zusätzlichen Benutzeroberflächenelementen aktualisiert, die einige nützliche Haken zum Hinzufügen von UI-Automatisierungstests bieten. Laden Sie das Projekt von GitHub herunter. Öffnen Sie das Projekt und führen Sie die Anwendung aus, um sicherzustellen, dass alles wie erwartet funktioniert. Sie sollten eine Benutzeroberfläche ähnlich der unten gezeigten sehen.
Bevor wir irgendwelche Tests schreiben, können Sie die Beispielanwendung ausprobieren, um sich mit ihrer Funktionalität vertraut zu machen. Als Benutzer können Sie Text in das Textfeld eingeben und auf die Schaltfläche tippen, um eine Beschriftung auf dem Bildschirm zu sehen, die die umgekehrte, eingegebene Zeichenfolge anzeigt.
Schritt 2: Erstellen eines UI-Automatisierungstests
Nun, da Sie mit der Beispielanwendung vertraut sind, ist es an der Zeit, einen UI-Automatisierungstest hinzuzufügen. UI Automation ist ein Tool, das in Instruments zu finden ist. Um die Beispielanwendung in Instruments auszuführen, wählen Sie im Menü von Xcode das Profil Product >. Wählen Sie Automation aus der Liste der Werkzeuge aus.
Das Hauptfenster von Instruments öffnet sich mit einem einzigen Instrument, dem Automation-Instrument (das Automation-Instrument führt UI Automation-Testfälle aus). In der unteren Hälfte des Fensters sehen Sie außerdem einen Bereich, der wie ein Texteditor aussieht. Dies ist der Skript-Editor. Hier werden Sie Ihre UI-Automatisierungstests schreiben. Für diesen ersten Test befolgen Sie die folgenden Anweisungen, indem Sie jede Zeile zum Skript im Skript-Editor hinzufügen.
Speichern Sie zunächst einen Verweis auf das Textfeld in einer Variablen.
var inputField = target.frontMostApp().mainWindow().textFields();
Setzen Sie den Wert des Textfelds.
inputField.setValue("hi");
Überprüfen Sie, ob der Wert erfolgreich gesetzt wurde, und wenn ja, bestehen Sie den Test. Ist dies nicht der Fall, wird der Test nicht bestanden.
Dieser Test ist zwar ziemlich trivial, aber dennoch von Nutzen. Wir haben gerade einen Test geschrieben, der das Vorhandensein eines Textfelds beim Start der Anwendung prüft und der testet, ob eine zufällige Zeichenkette als Wert für das Textfeld festgelegt werden kann. Wenn Sie mir nicht glauben, dann entfernen Sie das Textfeld aus dem Storyboard und führen Sie den Test aus. Sie werden sehen, dass er fehlschlägt.
Dieser Test demonstriert drei wichtige Aspekte beim Schreiben von UI-Automatisierungstests. Erstens zeigt er Ihnen, wie Sie auf ein einfaches Element der Benutzeroberfläche, das Textfeld, zugreifen können. Konkret greifen wir über target.frontMostApp().mainWindow().textFields()
auf ein Wörterbuch aller Textfelder in der Basisansicht der Anwendung zu und finden dann das Textfeld, das uns interessiert, indem wir nach dem Feld mit dem Schlüssel Input Field
suchen. Dieser Schlüssel ist eigentlich die Zugriffsbezeichnung des Textfeldes. In diesem Fall ist er im Storyboard definiert. Wir können die Kennzeichnung der Barrierefreiheit auch im Code festlegen, indem wir die Eigenschaft accessibilityLabel
auf NSObject
.
Der Zugriff auf das Hauptfenster der Anwendung, die vorderste Anwendung und das Ziel sind bei der Arbeit mit UI Automation üblich. Ich werde Ihnen später in diesem Tutorial zeigen, wie Sie dies einfacher und weniger umständlich gestalten können.
Zweitens zeigt Ihnen dies, dass Sie mit Elementen der Benutzeroberfläche auf dem Bildschirm interagieren können. In diesem Fall setzen wir den Wert des Textfeldes und imitieren so die Interaktion des Benutzers mit der Anwendung, indem wir Text in das Textfeld eingeben.
Und drittens zeigt das Beispiel auch eine Technik, um zu überprüfen, was in der Anwendung passiert. Wenn der Wert erfolgreich gesetzt wird, ist der Test erfolgreich. Wenn der Wert nicht gesetzt wird, schlägt der Test fehl.
Schritt 3: Speichern von Tests
Das Schreiben von Tests im Skript-Editor ist zwar bequem, wird aber schnell umständlich und schwer zu pflegen. Wenn Sie Instrumente verlassen, werden alle nicht gespeicherten Änderungen verworfen. Wir müssen die Tests, die wir schreiben, speichern. Kopieren Sie Ihren Test einfach in ein neues Dokument in Ihrem bevorzugten Texteditor und speichern Sie es. Sie finden die in diesem Tutorial erstellten Tests im Beispielprojekt unter Jumblify/JumblifyTests/AutomationTests.js.
Um den Test auszuführen, wählen Sie die mittlere Registerkarte im rechten Fenster neben dem Skript-Editor und wählen Sie Hinzufügen > Importieren.
Sie werden aufgefordert, das zu importierende Skript auszuwählen. Navigieren Sie zu dem gespeicherten Skript und importieren Sie es. Sie können das Skript im Skript-Editor noch ändern. Alle Änderungen werden automatisch in der von Ihnen erstellten externen Datei gespeichert.
Schritt 4: Tippen auf eine Schaltfläche
Lassen Sie uns unseren Test aktualisieren, um die Interaktion mit der Schaltfläche zu testen. Unser Test fügt bereits Text in das Textfeld ein, so dass wir nur noch Code hinzufügen müssen, um die Schaltfläche anzutippen. Überlegen wir zunächst, wie wir die Schaltfläche in der Ansicht finden können, damit sie angetippt werden kann. Es gibt mindestens drei Möglichkeiten, dies zu erreichen, und jeder Ansatz hat seine Nachteile.
Ansatz 1
Wir können programmatisch auf eine (X, Y)-Koordinate auf dem Bildschirm tippen. Wir tun dies mit der folgenden Codezeile:
target.tap({x: 8.00, y: 50.00});
Natürlich habe ich keine Ahnung, ob das überhaupt die Koordinaten der Schaltfläche auf dem Bildschirm sind, und ich werde mir auch keine Gedanken darüber machen, denn dieser Ansatz ist nicht das richtige Werkzeug für diese Aufgabe. Ich erwähne sie nur, damit Sie wissen, dass es sie gibt. Die Methode tap
auf target
zu verwenden, um auf eine Schaltfläche zu tippen, ist fehleranfällig, weil sich die Schaltfläche nicht immer an dieser bestimmten Koordinate befindet.
Ansatz 2
Es ist auch möglich, die Schaltfläche zu finden, indem man das Array der Schaltflächen des Hauptfensters durchsucht, ähnlich wie wir im ersten Test auf das Textfeld zugegriffen haben. Anstatt direkt über einen Schlüssel auf die Schaltfläche zuzugreifen, können wir ein Array von Schaltflächen im Hauptfenster abrufen und einen Array-Index hart codieren, um einen Verweis auf die Schaltfläche zu erhalten.
target.frontMostApp().mainWindow().buttons().tap();
Dieser Ansatz ist ein wenig besser. Wir kodieren keine Koordinaten, aber wir kodieren einen Array-Index, um die Schaltfläche zu finden. Wenn wir zufällig eine weitere Schaltfläche auf der Seite hinzufügen, kann dieser Test versehentlich unterbrochen werden.
Ansatz 3
Damit komme ich zur dritten Möglichkeit, die Schaltfläche auf der Seite zu finden, nämlich mit Hilfe von Barrierefreiheitsbezeichnungen. Durch die Verwendung einer Eingabehilfenbeschriftung können wir direkt auf die Schaltfläche zugreifen, so wie wir ein Objekt in einem Wörterbuch mit Hilfe eines Schlüssels finden würden.
target.frontMostApp().mainWindow().buttons().tap();
Wenn Sie jedoch die obige Zeile zum Skript hinzufügen und es ausführen, erhalten Sie einen Fehler.
Das liegt daran, dass wir die Eingabehilfenbeschriftung für die Schaltfläche noch nicht definiert haben. Wechseln Sie dazu zu Xcode und öffnen Sie das Storyboard des Projekts. Suchen Sie die Schaltfläche in der Ansicht und öffnen Sie den Identitätsinspektor auf der rechten Seite (Ansicht > Dienstprogramme > Identitätsinspektor). Vergewissern Sie sich, dass die Barrierefreiheit aktiviert ist, und setzen Sie die Beschriftung für die Schaltfläche auf „Jumblify Button“.
Um den Test erneut auszuführen, müssen Sie die Anwendung in Xcode ausführen, indem Sie „Produkt > Ausführen“ wählen und dann die Anwendung erneut profilieren, indem Sie „Produkt > Profil“ wählen. Dadurch werden die Tests ausgeführt, und jeder Test sollte jetzt erfolgreich sein.
Schritt 5: Überprüfen der durcheinandergewürfelten Zeichenfolge
Wie ich bereits erwähnt habe, nimmt unsere Anwendung eine Textzeichenfolge als Eingabe entgegen, und wenn der Benutzer auf die Schaltfläche tippt, wird die umgekehrte Zeichenfolge angezeigt. Wir müssen noch einen weiteren Test hinzufügen, um zu überprüfen, ob die Eingabezeichenfolge richtig umgedreht ist. Um zu überprüfen, ob die UILabel
mit der richtigen Zeichenfolge gefüllt ist, müssen wir herausfinden, wie wir auf die UILabel
verweisen und die angezeigte Zeichenfolge überprüfen können. Dies ist ein häufiges Problem beim Schreiben von Automatisierungstests, nämlich herauszufinden, wie man auf ein Element in der Anwendung verweist, um eine Aussage darüber zu treffen.
Es gibt eine Methode für fast jedes Objekt in der UI Automation API, logElementTree
. Diese Methode protokolliert die verschachtelten Elemente eines bestimmten Elements. Dies ist sehr nützlich, um die Hierarchie der Elemente in der Anwendung zu verstehen und hilft dabei herauszufinden, wie man ein bestimmtes Element anvisieren kann.
Lassen Sie uns sehen, wie dies funktioniert, indem wir den Elementbaum des Hauptfensters protokollieren. Werfen Sie einen Blick auf die folgende Codezeile:
target.frontMostApp().mainWindow().logElementTree();
Wenn Sie diese Zeile zum Testskript hinzufügen, erhalten Sie folgende Ausgabe:
Wie Sie sehen können, gibt es ein Unterelement UIAStaticText
des UIAWindow
und Sie können auch sehen, dass es den Namen ih
hat, der zufällig auch der umgekehrte String ist, den wir überprüfen müssen. Um unseren Test zu vervollständigen, müssen wir jetzt nur noch Code hinzufügen, um auf dieses Element zuzugreifen und zu überprüfen, ob es vorhanden ist.
Warum müssen wir nur überprüfen, ob das Element UIAStaticText
vorhanden ist? Da der Name des Elements die umgekehrte Zeichenkette der Eingabezeichenkette ist, bestätigt die Überprüfung seines Vorhandenseins, dass die Zeichenkette korrekt umgekehrt wurde. Wenn das Element nicht vorhanden ist, wenn es über den Namen – die umgekehrte Zeichenfolge – referenziert wird, bedeutet dies, dass die Zeichenfolge nicht korrekt umgekehrt wurde.
4. Kratzen an der Oberfläche
Es gibt so viele andere Möglichkeiten, wie ein Endbenutzer mit einem iOS-Gerät interagieren kann, während er Ihre App verwendet. Das bedeutet, dass es viele weitere Möglichkeiten gibt, diese Interaktionen mit UI Automation zu simulieren. Anstatt zu versuchen, eine umfassende Liste dieser Interaktionen zu erfassen, verweise ich Sie auf die Referenzdokumentation zur UI-Automatisierung.
Für jeden Objekttyp, mit dem Sie interagieren können, können Sie die Liste der für dieses Objekt verfügbaren Methoden anzeigen. Einige Methoden dienen dazu, Attribute über das Objekt abzurufen, während andere dazu dienen, die Touch-Interaktion zu simulieren, wie z. B. flickInsideWithOptions
auf UIAWindow
.
Aufzeichnung einer Sitzung
Wenn Sie versuchen, immer kompliziertere Anwendungen mit UI Automation zu testen, werden Sie feststellen, dass es manchmal ziemlich mühsam ist, wiederholt logElementTree
zu verwenden, um das gesuchte Element zu finden. Dies wird auch bei Anwendungen mit einer komplexen Ansichtshierarchie oder Navigation mühsam und komplex. In diesen Fällen können Sie eine andere Funktion von Instruments verwenden, um eine Reihe von Benutzerinteraktionen aufzuzeichnen. Das Beste daran ist, dass Instruments den JavaScript-Code für die UI-Automatisierung generiert, der für die Reproduktion der aufgezeichneten Interaktionen benötigt wird. So können Sie es selbst ausprobieren.
Suchen Sie in Instruments bei ausgewähltem Automatisierungsinstrument nach der Aufnahmeschaltfläche am unteren Rand des Fensters.
Wenn Sie auf die Aufnahmeschaltfläche klicken, startet Instruments eine Aufnahmesitzung, wie im Screenshot unten gezeigt.
Instruments startet Ihre Anwendung im iOS-Simulator und Sie können mit ihr interagieren. Instruments generiert ein Skript basierend auf Ihren Interaktionen in Echtzeit. Probieren Sie es aus. Drehen Sie den iOS Simulator, tippen Sie an zufälligen Stellen, führen Sie eine Wischgeste aus usw. Es ist eine wirklich nützliche Methode, um die Möglichkeiten der UI-Automatisierung zu erforschen.
Vermeiden einer monolithischen Codebasis
Wie Sie sich wahrscheinlich vorstellen können, wird es schnell schwierig, die Testdatei zu pflegen, wenn wir ihr immer mehr Tests hinzufügen, die wir mit derselben Methode erstellt haben. Was können wir tun, um das zu verhindern? In meinen Tests mache ich zwei Dinge, um dieses Problem zu lösen:
- Ein Test für eine Funktion: Das bedeutet, dass die Tests, die wir schreiben, auf einen bestimmten Teil der Funktionalität ausgerichtet sein müssen. Ich gebe ihm sogar einen passenden Namen, z. B.
testEmptyInputField
. - Gruppieren Sie verwandte Tests in einer Datei: Ich gruppiere auch verwandte Tests in derselben Datei. So bleibt der Code in einer Datei überschaubar. Das macht es auch einfacher, einzelne Teile der Funktionalität zu testen, indem man die Tests in einer bestimmten Datei ausführt. Außerdem können Sie ein Masterskript erstellen, in dem Sie die Funktionen oder Tests aufrufen, die Sie in anderen Testdateien gruppiert haben.
Im folgenden Codeschnipsel importieren wir eine JavaScript-Datei, wodurch uns die Funktionen in dieser JavaScript-Datei zur Verfügung stehen.
#import "OtherTests.js"
Abschluss
In diesem Tutorial haben Sie den Wert von Tests auf höherer Ebene kennengelernt und erfahren, wie UI-Automatisierung dabei helfen kann, diese Lücke zu schließen. Es ist ein weiteres Werkzeug in Ihrem Werkzeugkasten, um sicherzustellen, dass Sie zuverlässige und robuste Anwendungen liefern.