E2E Testing in Angular 2 From Zero To Hero (Final Part)
Liebe zukünftige Meister des Angular 2 E2E Testing.
Das ist es. Am Ende dieser Lektion haben Sie endlich alle Werkzeuge, um funktionale Tests für Ihre Angular 2-Anwendungen zu erstellen. Keine Ausreden mehr: Sie haben die Macht!
Wir werden uns zuerst mit Locators vertraut machen, dann werden wir sehen, wie großartig Page Objects sein können, gefolgt von der Handhabung von Asynchronität und schließlich dem einfachsten Teil, dem Auslösen von Actions.
Wenn Sie die Grundlagen nicht kennen, sollten Sie dort anfangen, sonst sind Sie ein wenig verloren.
Locators
Eine, wenn nicht die wichtigste Sache beim E2E Testen ist es, die Elemente zu finden, die Sie in Ihrer Ansicht testen wollen. Meistens werden Sie sich die Frage stellen „Warum kann ich dieses **** Element nicht finden?“, gefolgt von einem „oooohhhhh“.
Sie haben viele Möglichkeiten, dies zu tun. Die meisten davon hängen von Ihrer Anwendung ab. Um Ihre Elemente zu finden, werden Sie eine Reihe von Locators verwenden. Meistens können Sie Ihre Elemente finden durch:
- Klassenname.
- Id.
- Model.
- Binding.
Für die kommenden Tests werden wir diese Vorlage verwenden.html:
<div class="parent2"> <div class="parent1"> <div class="nested-class" style="color:blue;"> I am a nested element </div> </div></div>
Lassen Sie uns auf nested-class und nested-id konzentrieren.
By Class:
Wir greifen hier unser Element mit element(by.css(selector)) und testen dann, ob es vorhanden ist oder nicht.
By Id:
it("should find the nested id", () => { let elem = element(by.id("nested-id")); expect(elem.getText()).toBe("I am a nested element");});
Wir greifen hier unser Element mit element(by.id(elem-id)) und testen dann, ob es vorhanden ist oder nicht.
Die folgenden Locators sind sehr nützlich in AngularJS, aber noch nicht in Angular 2 implementiert, also behalte sie vorerst auf der Seite.
By Model:
it("should find the model", () => { let elem = element(by.model("modelToFind")); expect(elem.isPresent()).toBeTruthy();});
By Bindings:
it("should find the binding", () => { let elem = element(by.model("bindingToFind")); expect(elem.isPresent()).toBeTruthy();});
Um deine Tests zu debuggen, kannst du einfach „browser.pause()“ in deinen Test einfügen, du wirst in der Lage sein, alle vorherigen Anweisungen auszuführen und anzuhalten, wo immer du willst.
Sobald die Pause erreicht ist, erscheint ein Bildschirm, der diesem ähnelt:
Wie Sie in diesem Bild sehen können, müssen Sie repl eingeben, um auf den Fahrersitz zu gelangen.
Angenommen, Sie haben keinen Test und wollen nur mit Protractor herumspielen. Sie können einfach in Ihr Terminal eingeben:
protractor --elementExplorer
Wenn Sie Probleme mit Ihrem Pfad haben, können Sie eingeben:
./node_modules/protractor/bin/elementexplorer.js
Sie müssen diesmal nicht repl. eingeben, verwenden Sie einfach das Browser-Objekt und schon können Sie loslegen!
Seitenobjekte
Was ist, wenn Sie Tests haben, die das gleiche Szenario haben? Werden Sie Ihren Code überall kopieren und einfügen? Was ist, wenn sich das Szenario ändert? Jetzt müssen Sie alle Dateien durchgehen und die Änderungen vornehmen.
Hier werden Pages Objects sehr nützlich. Write Once, Share Everywhere!
Ein Page Object ist ein Objekt, das die Elemente und Szenarien zu einer Seite enthält.
Zunächst ein sehr einfaches Seitenobjekt:
export class HomePage { nestedClass; constructor() { this.nestedClass = element(by.css(".nested-class")); }}
Dann verwenden wir es in unserem Test:
Wir importieren das Seitenobjekt, erstellen eine Instanz und verwenden dann seine Eigenschaft.
Asynchrone Abenteuer
Jetzt, meine Freunde, könnt ihr auf alle Elemente auf eurer Seite zugreifen! Ich meine fast :).
Es wird einige Sonderfälle geben.
Wenn Sie das (Un-)Glück hatten, mit jQuery zu arbeiten, müssen Sie mit document.ready() vertraut sein.
Durch die asynchrone Natur von JavaScript wird es Fälle geben, in denen Sie versuchen werden, auf ein Element zuzugreifen, bevor es auf der Seite erschienen ist.
Um damit umzugehen, müssen Sie eine Funktion von Protractor verwenden, um zu warten, bis Ihr Element bereit ist, bevor Sie es suchen.
Hier ist ein Beispiel, das eine Schaltfläche nach Ablauf einer Zeitüberschreitung anzeigt.
Erst die Klasse, die die Zeitüberschreitung enthält:
export class Home { isHidden = true; triggerTimeOut = ((){ setTimeout(() => this.isHidden = false, 2250) })}
Dann die template.html:
Wir haben hier eine Schaltfläche, die unsere Zeitüberschreitung auslöst, sobald die Zeitüberschreitung abgelaufen ist, wird der Text angezeigt.
Hier sind die Tests.
Wir finden unsere Schaltfläche, klicken darauf, versuchen unseren Text zu finden, ABER wir erwarten, dass er nicht vorhanden ist.
Und hier ist die Art und Weise, wie wir diesen Fall behandeln ;).
Wir verwenden „browser.wait“ kombiniert mit „browser.isElementPresent“, um unseren Locator zu testen. Nach 5 Sekunden wird der Rest des Codes ausgeführt. Vergessen Sie nicht, hier einen Timer zu setzen, sonst werden Ihre Tests für immer blockiert!
Wenn also eines Ihrer Elemente hier sein sollte, Sie es aber nicht bekommen können, sollte Ihr Bauchgefühl Ihnen sagen, dass Sie sich an das erinnern sollten, was Sie hier gerade gelesen haben.
Aktionen
Nun, da Sie Ihr kostbares Element haben, haben Sie 90% der Arbeit erledigt!
Wenn Sie es nicht finden können, funktioniert Ihre Anwendung entweder nicht so, wie sie sollte (deshalb machen wir Tests) oder Sie müssen besser im Testen werden und weniger Zeit mit Pokemon GO verbringen, um nachts um 1 Uhr Dratinis in der Nähe eines Flusses zu jagen (das haben wir alle schon erlebt …).
Lassen Sie uns mit den Aktionen weitermachen, die Sie auf ein Element anwenden können. Hier sind sie:
Wir verwenden Protractor, das auf WebDriver basiert. Wenn Sie mehr ausgefallene Aktionen benötigen, können Sie sich ansehen, was hier verfügbar ist.
Lassen Sie uns einige davon testen.
Für die template.html:
<input type="text" />
Wir werden ein wenig mit der Texteingabe spielen. Schnelles Quiz, was macht dieser Test (lesen Sie nicht die Beschreibung)?
Lösung: Wir holen unsere Eingabe, geben „Some text“ ein, testen, dass wir den Wert gesetzt haben, löschen ihn und testen schließlich, dass der Wert leer ist.
Schließlich können wir uns fragen, was der beste Weg ist, um Aktionen auszulösen? Dieser Link hier zeigt eine der Schwächen der Verwendung von JavaScript anstelle von WebDriver.
Sicherlich ist das Schreiben in JavaScript viel kompakter, aber es bringt einige Risiken mit sich!
Sie können mit einem Element alles machen, was Sie wollen. Der beste Weg, es zu testen, ist, die verfügbaren Matcher zu verwenden. Warum? Weil sie elegant und nahe an der menschlichen Sprache sind, Beispiel:
expect(apples.length !== 0).toBe(true);
expect(apples).not.toBeEmpty();
Abschluss
Dies war der letzte Beitrag dieser Serie, jetzt haben Sie 90% der Fähigkeiten, um Ihre Angular 2 Anwendungen zu testen. Die restlichen 10% werden Sie durch Erfahrung erlangen. Denken Sie daran, zuerst Ihre Elemente mit Locators zu bekommen, dann setzen Sie die, die in einem Page Object repliziert werden könnte, wenn Sie Ihr Element nicht finden können und Sie sind sicher, dass es hier ist, könnte es sein, weil es noch nicht erschienen ist und Sie müssen die Asynchronität zu behandeln. Testen Sie schließlich die **** aus Ihren Elementen mit Actions.