Ich versuche, meinem Projekt einige Unit-Tests hinzuzufügen, um View-Controller zu testen. Jedoch scheint ich Probleme mit scheinbar einfachen Dingen zu haben. Ich habe ein Beispielprojekt erstellt, auf das ich verweisen werde. Ссылка
Das Beispiel enthält einen UINavigationController als initialen View-Controller. Der Root-View-Controller des UINavigationControllers ist FirstViewController. Es gibt eine Schaltfläche auf FirstViewController, die zu SecondViewController wechselt. In SecondViewController gibt es ein leeres Textfeld.
Die zwei Tests, die ich hinzufügen möchte, sind:
1) Überprüfen Sie die Schaltfläche Titel in FirstViewController ist "Next Screen".
2) Überprüfen Sie das Textfeld in SecondViewController ist leer, "".
Ich habe gehört, dass Berichte über das Hinzufügen Ihrer schnellen Dateien sowohl zum Hauptziel als auch zum Testziel keine gute Übung sind. Vielmehr ist es besser, das, worauf Sie in Ihren Tests zugreifen möchten, öffentlich zu machen und das Hauptziel in die Tests zu importieren. Das habe ich getan. (Ich habe auch das "Defines Module" für das Hauptziel auf YES gesetzt, wie ich es auch in einigen Artikeln gelesen habe).
In FirstViewControllerTests habe ich den ersten View-Controller mit folgendem Inhalt instanziiert:
%Vor%Und ich habe den Test hinzugefügt:
%Vor%Ebenso habe ich es für SecondViewControllerTest eingerichtet mit:
%Vor%Und der Test:
%Vor%Beide scheitern und ich bin mir nicht sicher, warum. Mein Verdacht ist, dass die Art, wie ich die View-Controller instanziiere, nicht korrekt ist. Ist der beste Weg, die View-Controller zu instanziieren, das Storyboard zu verwenden (genau wie wenn es im echten Leben laufen würde)? Oder ist es akzeptabel, über:
instanziiert zu werden %Vor%Was haben Sie mit TDD und View Controllern in swift zu tun?
Ich verwende Swift mit XCode 6.1.1.
Vielen Dank im Voraus.
Gelöst
Ok, nachdem ich die Antworten von Modocache und Mike Taverne betrachtet habe, habe ich meine Lösung gefunden und ich habe ein paar Dinge gelernt, die ich unten aufschreiben werde.
1) Ich habe alles class / method / variable gemacht, das ich öffentlich testen möchte. Ich muss die Swift-Dateien nicht zum Testziel hinzufügen.
2) Ich musste nur "Defines Module" für das "Main" -Ziel festlegen (im Gegensatz zum "Test" -Ziel oder dem gesamten Projekt)
3) Wenn das Storyboard instanziiert wird, sollte das Bundle auf Nil und nicht auf NSBundle (forClass: self.dynamicType) gesetzt werden, da sonst die Tests fehlschlagen.
4) Wie der Modocache sagt, ist es gut, Ihrem View-Controller eine StoryboardID zu geben und sie so zu instanziieren:
%Vor%Wenn Sie den View-Controller jedoch wie folgt instanziieren, wird der View-Controller NUR instanziiert, und nicht alle Navigations-Controller, in die er eingebettet sein könnte. Dies bedeutet,
zu versuchen %Vor%führt zu keiner Ausnahme. Das habe ich mit
bestätigt %Vor%was zu einem erfolgreichen Test geführt hat.
Da ich den Status der Navigationsleiste in FirstViewController überprüfen wollte, müssen Sie den View-Controller wie folgt instanziieren:
%Vor%Jetzt den Test durchführen
%Vor%führt zu einem erfolgreichen Test.
5) Lassen Sie _ = viewController.view tatsächlich viewDidLoad () auslösen, was durch einen Test bestätigt wurde
6) let _ = viewController.view löst nicht viewWillAppear () aus, und ich nehme auch alles danach an. viewController.viewWillAppear (false / true) muss manuell aufgerufen werden, um es auszulösen (Bestätigt durch einen Test).
Hoffentlich wird das den Menschen helfen. Ich werde das aktualisierte Projekt an GitHub weiterleiten (Link oben), wenn jemand damit herumspielen möchte.
Update # 2
Nach all dem oben Gesagten konnte ich immer noch nicht herausfinden, wie ich vom ersten View-Controller zum zweiten View-Controller übergehen sollte (damit ich Navigationsleisten-Eigenschaften in SecondViewControllerTests.swift testen kann). Ich habe es versucht
%Vor%was einen Fehler verursacht hat.
Ich habe es auch versucht
%Vor%was nicht funktioniert hat.
Ich habe es schließlich versucht
%Vor%was perfekt zu meinen Tests gepasst hat (erlaubte mir den Zugriff auf die Eigenschaften der Navigationsleiste)!
Ich stimme @ MikeTavernes Antwort zu: Ich bevorzuge den Zugriff auf -[UIViewController view]
, um -[UIViewController viewDidLoad]
auszulösen, anstatt sie direkt aufzurufen. Prüfen Sie, ob die Testfehler für FirstViewController
wegfallen, wenn Sie diese stattdessen verwenden:
Ich würde auch empfehlen, beide View-Controller-IDs in Ihrem Storyboard anzugeben. Dadurch können Sie sie direkt instanziieren, ohne über UINavigationController
:
Schau dir meinen Vortrag über das Testen von UIViewController
bei Brooklyn Swift für Details an: Ссылка (meine Präsentation beginnt um die 37 Marke "50").
Ich habe vor kurzem Unit-Testing-View-Controller gestartet und es stellt einige einzigartige Herausforderungen dar.
Eine Herausforderung besteht darin, die Ansicht zu laden. Wenn Sie Ihr Setup für FirstViewController betrachten, versuchen Sie dies mit viewController.viewDidLoad ().
Mein Vorschlag ist, diese Zeile durch folgendes zu ersetzen:
lass dummy = viewController.view
Der Zugriff auf die Eigenschaft .view erzwingt das Laden der Ansicht. Dies wird die .viewDidLoad in Ihrem ViewController auslösen, also rufen Sie diese Methode nicht explizit in Ihrem Test auf.
Dieser Ansatz wird von einigen Leuten als Hacky angesehen, aber er ist einfach und effektiv. (Siehe Die Methode "Ansicht erzwingen" erzwingen, um Teilansichten frühzeitig zu laden )
Nebenbei bemerkt, ich finde die beste Methode zum Testen von View-Controllern darin, so viel Code wie möglich aus den View-Controllern in andere Klassen zu übertragen, die leichter getestet werden können.
Wenn Ihr View-Controller in einem Storyboard definiert ist, müssen Sie ihn auf diese Weise instanziieren, damit Ihre Outlets ordnungsgemäß eingerichtet werden können. Versuchen, es wie eine normale Klasse zu initialisieren, wird nicht funktionieren.
Tags und Links unit-testing ios tdd swift uiviewcontroller