Niemand möchte fehlerhafte Software versenden. Um sicherzustellen, dass Sie eine mobile Anwendung von höchster Qualität veröffentlichen, ist weitaus mehr erforderlich als ein manueller Qualitätssicherungsprozess. Neue Geräte und Betriebssysteme werden jedes Jahr der Öffentlichkeit zugänglich gemacht. Dies bedeutet, dass es eine ständig wachsende Kombination von Bildschirmgrößen und Betriebssystemversionen gibt, auf denen Sie Ihre mobile Anwendung testen müssen. Dies ist nicht nur extrem zeitaufwändig, sondern der Versuch, Ihre iOS-Anwendung durch manuelles Testen zu testen, vernachlässigt einen ganzen Teil des modernen Software-Engineering-Prozesses und automatisierte Qualitätssicherungstests.
In der heutigen Welt gibt es viele Tools, mit denen die von Ihnen geschriebene Software automatisch getestet werden kann. Einige dieser Tools werden über ein Open Source-Modell gepflegt, es gibt jedoch auch einen Kernsatz von Apple. Mit jeder neuen Version des iOS-SDK hat Apple sein Engagement für die Verbesserung der verfügbaren Tools für Entwickler zum Testen des von ihnen geschriebenen Codes unterstrichen. Für iOS-Entwickler, die sich mit automatisierten Tests noch nicht auskennen, sind Apples Tools ein guter Anfang.
In diesem Lernprogramm erhalten Sie Anweisungen zur Verwendung eines Tools, das von Apple für automatisierte Tests (XCTest) bereitgestellt wird. XCTest ist das Appliance-Test-Framework von Apple. Unit-Tests sind automatisierte Tests, bei denen der Code auf der untersten Ebene überprüft wird. Sie schreiben Objective-C-Code, der Methoden aus Ihrem "Produktionscode" aufruft, und überprüfen, ob der getestete Code tatsächlich das tut, was er tun soll. Sind die Variablen richtig gesetzt? Ist der Rückgabewert korrekt??
Mit dem XCTest-Framework geschriebene Tests werden möglicherweise wiederholt mit dem Code Ihrer Anwendung ausgeführt, um die Gewissheit zu gewinnen, dass Sie ein fehlerfreies Produkt erstellen, da neue Codeänderungen die vorhandene Funktionalität nicht beeinträchtigen.
Standardmäßig wird jedes neue Xcode-Projekt mit einem guten Ausgangspunkt zum Schreiben von Komponententests erstellt. Dies beinhaltet drei Dinge:
Sehen wir uns die Struktur eines iOS-Gerätetests an. Ein einzelner Komponententest wird als einzelne Methode in jeder Unterklasse von dargestellt XCTestCase
wo die Methode zurückkehrt Leere
, nimmt keine Parameter und der Methodenname beginnt mit Prüfung
.
- (void) testSomething
Glücklicherweise macht Xcode das Erstellen von Testfällen einfach. Bei neuen Xcode-Projekten wird ein erster Testfall für Sie in einer separaten Dateigruppe erstellt, deren Name mit dem Wort versehen ist Tests.
Ich habe ein Beispielprojekt erstellt, das als Referenz für die Beispiele in diesem Lernprogramm verwendet werden kann. Laden Sie das Projekt von GitHub herunter und öffnen Sie es in Xcode.
Im Beispielprojekt finden Sie die Gruppe der Tests im genannten Ordner JumblifyTests.
Um Ihren ersten Testfall zu erstellen, klicken Sie mit der rechten Maustaste auf die Dateigruppe, JumblifyTests, und wählen Sie Neue Datei. Wählen Testfallklasse von dem iOS> Quelle Abschnitt, und geben Sie der neuen Unterklasse einen Namen.
Die typische Benennungskonvention besteht darin, den Testfall so zu benennen, dass er der Name der entsprechenden getesteten Klasse mit dem Suffix ist Tests. Da werden wir das testen JumblifyViewController
Klasse, nennen Sie das XCTestCase
Unterklasse JumblifyViewControllerTests
.
In der Marke neu XCTestCase
Unterklasse werden Sie vier Methoden sehen. Zwei davon sind selbst Tests. Kannst du sie identifizieren? Denken Sie daran, dass die Namen der Testmethoden mit dem Wort "test" beginnen..
Wenn Sie es nicht herausgefunden haben, werden standardmäßig die Testmethoden erstellt testExample
und testPerformanceExample
.
Löschen Sie beide Tests, da wir unsere Tests von Grund auf schreiben werden. Die anderen beiden Methoden, Konfiguration
und niederreissen
, werden von der Superklasse überschrieben, XCTestCase
. Das ist einzigartig Konfiguration
und niederreissen
werden vor bzw. nach dem Aufruf jeder Testmethode aufgerufen. Sie sind nützliche Orte, um Code zu zentralisieren, der vor oder nach dem Aufruf jeder Testmethode ausgeführt werden soll. Aufgaben wie häufige Initialisierung oder Bereinigung finden Sie hier.
Importieren Sie die Header-Datei von JumblifyViewController
Klasse und fügen Sie eine Eigenschaft des Typs hinzu JumblifyViewController
zum XCTestCase
Unterklasse.
@ property (nonatomic) JumblifyViewController * vcToTest;
In dem Konfiguration
Methode, initialisieren Sie die Eigenschaft wie unten gezeigt.
- (void) setUp [super setUp]; self.vcToTest = [[JumblifyViewController-Zuordnung] init];
Wir werden jetzt einen Test schreiben, um das zu testen reverseString:
Methode der JumblifyViewController
Klasse.
Erstellen Sie eine Testmethode, die das instantiierte verwendet vcToTest
Objekt zum Testen der reverseString:
Methode. In dieser Testmethode erstellen wir eine NSString
Objekt und übergeben Sie es an den View Controller reverseString:
Methode. Es ist gängige Konvention, Ihrem Test einen aussagekräftigen Namen zu geben, um deutlich zu machen, was der Test testet.
- (void) testReverseString NSString * originalString = @ "himynameisandy"; NSString * reversedString = [self.vcToTest reverseString: originalString];
Zu diesem Zeitpunkt haben wir noch nichts Nützliches getan, weil wir das noch nicht getestet haben reverseString:
Methode noch. Was wir tun müssen, ist, die Ausgabe von zu vergleichen reverseString:
Methode mit dem, was wir als Ausgabe erwarten.
Das XCTAssertEqualObjects
Funktion ist Teil des XCTest-Frameworks. Das XCTest-Framework bietet viele andere Methoden, um Assertions über den Anwendungsstatus zu treffen, wie z. B. Variablengleichheit oder Boolesche Ausdrucksergebnisse. In diesem Fall haben wir festgestellt, dass zwei Objekte gleich sein müssen. Wenn dies der Fall ist, ist der Test erfolgreich, und wenn nicht, schlägt der Test fehl. In der Dokumentation von Apple finden Sie eine umfassende Liste der durch das XCTest-Framework bereitgestellten Zusicherungen.
- (void) testReverseString NSString * originalString = @ "himynameisandy"; NSString * reversedString = [self.vcToTest reverseString: originalString]; NSString * expectedReversedString = @ "ydnasiemanymih"; XCTAssertEqualObjects (expectedReversedString, reversedString, @ "Die umgekehrte Zeichenfolge stimmte nicht mit der erwarteten Umkehrung überein");
Wenn Sie versuchen, den Code an dieser Stelle zu kompilieren, wird beim Aufruf eine Warnung angezeigt reverseString:
aus dem Testfall. Das reverseString:
Methode ist eine private Methode der JumblifyViewController
Klasse. Das bedeutet, dass andere Objekte diese Methode nicht aufrufen können, da sie nicht in der Header-Datei von definiert ist JumblifyViewController
Klasse.
Während das Schreiben testbaren Codes ein Mantra ist, dem viele Entwickler folgen, möchten wir unseren getesteten Code nicht unnötig ändern. Aber wie nennen wir das Private? reverseString:
Methode der JumblifyViewController
Klasse in unseren Tests? Wir könnten eine öffentliche Definition des hinzufügen reverseString:
Methode in die Header-Datei des JumblifyViewController
Klasse, aber das bricht das Einkapselungsmuster.
Eine Lösung ist das Hinzufügen einer privaten Kategorie in der JumblifyViewController
Klasse, um die zu entlarven reverseString:
Methode. Wir fügen diese Kategorie dem hinzu XCTestCase
Unterklasse, was bedeutet, dass es nur in dieser Klasse verfügbar ist. Durch das Hinzufügen dieser Kategorie wird der Testfall ohne Warnungen oder Fehler kompiliert.
@interface JumblifyViewController (Test) - (NSString *) reverseString: (NSString *) stringToReverse; @Ende
Lassen Sie uns unsere Tests durchführen, um sicherzustellen, dass sie erfolgreich sind. Es gibt verschiedene Möglichkeiten, Komponententests für eine iOS-Anwendung auszuführen. Ich bin ein Tastaturkürzel-Junkie. Meine am häufigsten verwendete Methode zum Ausführen meiner Unit-Tests für meine Anwendung ist das Drücken von Befehl-U. Diese Tastenkombination führt alle Tests für Ihre Anwendung aus. Sie können dieselbe Aktion auch ausführen, indem Sie auswählen Prüfung von dem Produkt Speisekarte.
Wenn Ihre Testsuite wächst oder Sie eine testgetriebene Entwicklung implementieren möchten, kann die Ausführung Ihrer Testsuite zu zeitaufwändig werden. Oder es könnte Ihren Workflow behindern. Ein sehr nützlicher Befehl, eingebettet in Xcodes Menü, in den ich mich verliebt habe, ist Befehl-Option-Steuerung-U. Diese Verknüpfung löst einen Befehl aus, der den Test ausführt, in dem sich der Cursor gerade befindet. Sobald Sie Ihre Testsuite ausgearbeitet und abgeschlossen haben, sollten Sie immer die gesamte Testsuite ausführen. Das Ausführen eines einzelnen Tests ist hilfreich, wenn Sie einen neuen Test schreiben oder wenn Sie einen fehlgeschlagenen Test debuggen.
Der Befehl zum Ausführen eines Tests wird durch das Kommando ergänzt Befehl-Option-Steuerung-G, was wiederholt den letzten Testlauf. Dies kann die gesamte Testsuite sein oder nur der letzte Test, an dem Sie gerade arbeiten. Dies ist auch nützlich, wenn Sie sich von den Tests, an denen Sie gerade arbeiten, entfernt haben und noch im Debugging-Prozess sind.
Sie können Ihre Testergebnisse an mehreren Stellen sehen. Einer dieser Orte ist der Test Navigator zur Rechten.
Eine andere Möglichkeit besteht darin, die Dachrinne zu betrachten Quelleditor.
Wenn Sie an einer dieser beiden Stellen auf den grünen Diamanten mit dem weißen Häkchen klicken, wird der betreffende Test erneut ausgeführt. Bei einem fehlgeschlagenen Test sehen Sie einen roten Diamanten mit einem weißen Kreuz in der Mitte. Wenn Sie darauf klicken, wird der betreffende Test erneut ausgeführt.
Xcode 6 hat zwei neue aufregende Ergänzungen zum Komponententest unter iOS und OS X eingeführt, die die asynchrone Funktionalität testen und die Leistung eines bestimmten Codeteils messen.
Vor Xcode 6 gab es keine gute Möglichkeit, asynchronen Code zu testen. Wenn Ihr Gerätetest eine Methode aufgerufen hat, die asynchrone Logik enthielt, konnten Sie die asynchrone Logik nicht überprüfen. Der Test würde abgeschlossen sein, bevor die asynchrone Logik in der zu testenden Methode ausgeführt wurde.
Zum Testen von asynchronem Code hat Apple eine API eingeführt, mit der Entwickler eine Erwartung definieren können, die erfüllt sein muss, damit der Test erfolgreich abgeschlossen werden kann. Der Ablauf ist wie folgt: Definieren Sie eine Erwartung, warten Sie, bis die Erwartung erfüllt ist, und erfüllen Sie die Erwartung, wenn die Ausführung des asynchronen Codes abgeschlossen ist. Schauen Sie sich das Beispiel unten zur Verdeutlichung an.
- (void) testDoSomethingThatTakesSomeTime XCTestExpectation * completionExpectation = [SelbsterwartungWithDescription: @ "Lange Methode"]; [self.vcToTest doSomethingThatTakesSomeTimesWithCompletionBlock: ^ (Ergebnis NSString *) XCTAssertEqualObjects (@ "Ergebnis", Ergebnis, @ "Ergebnis war nicht korrekt!"); [CompletionExpectation erfüllen]; ]; [self waitForExpectationsWithTimeout: 5.0 handler: nil];
In diesem Beispiel testen wir die doSomethingThatTakesSomeTimesWithCompletionBlock
Methode. Wir möchten den Erfolg oder Misserfolg unseres Tests von dem Wert abhängen, der in dem von der getesteten Methode aufgerufenen Completion-Block zurückgegeben wird.
Dazu definieren wir zu Beginn der Testmethode eine Erwartung. Am Ende der Testmethode warten wir, bis die Erwartung erfüllt ist. Wie Sie sehen, können wir auch einen Timeout-Parameter übergeben.
Die eigentliche Zusicherung des Tests erfolgt innerhalb des Completion-Blocks der zu testenden Methode, in dem wir auch die zuvor definierten Erwartungen erfüllen. Wenn der Test ausgeführt wird, wartet der Test daher, bis die Erwartung erfüllt ist, oder er schlägt fehl, wenn das Zeitlimit abläuft und die Erwartung nicht erfüllt wird.
Eine weitere Ergänzung zum Komponententest in Xcode 6 ist die Möglichkeit, die Leistung eines Codes zu messen. Auf diese Weise können Entwickler Einblick in die spezifischen Timing-Informationen des getesteten Codes erhalten.
Mit Leistungstests können Sie die Frage beantworten "Wie ist die durchschnittliche Ausführungszeit für diesen Code"? Wenn es einen Abschnitt gibt, der besonders empfindlich auf Änderungen in Bezug auf die Ausführungszeit ist, können Sie Leistungstests verwenden, um die Ausführungszeit zu messen.
Sie können auch eine Baseline-Ausführungszeit definieren. Dies bedeutet, dass der Test fehlschlägt, wenn der getestete Code erheblich von dieser Basislinie abweicht. Xcode führt den getesteten Code wiederholt aus und misst seine Ausführungszeit. Verwenden Sie zum Messen der Leistung eines Codes den measureBlock:
API wie unten gezeigt.
- (void) testPerformanceReverseString NSString * originalString = @ "himynameisandy"; [self measureBlock: ^ [self.vcToTest reverseString: originalString]; ];
Klicken Sie auf die Informationsmeldung, die angezeigt wird.
Legen Sie die Grundausführungszeit für den Leistungstest fest oder bearbeiten Sie sie.
In diesem Lernprogramm haben Sie gelernt, wie Sie mit Xcode Komponententests erstellen, um eine iOS-Anwendung auf programmatische und automatisierte Weise zu überprüfen. Probieren Sie es aus, entweder auf einer vorhandenen Code-Basis oder auf etwas Neuem. Ganz gleich, ob Sie sich uneingeschränkt für Unit-Tests einsetzen oder hier und da ein paar Tests hinzufügen: Sie fügen Ihrem Projekt nur einen Mehrwert hinzu, indem Sie stärker geprüfte Software schreiben, die weniger anfällig für zukünftige Änderungen ist. Unit-Tests sind nur der Anfang eines automatisierten Softwaretests. Es gibt mehrere zusätzliche Testebenen, die Sie einer iOS-Anwendung hinzufügen können.