4 Minuten Lesezeit (809 Worte)

End-to-End-Tests in Angular mit Cypress

Über die Jahre sind viele verschiedene Test-Frameworks entstanden, die Anwendungen auf unterschiedlichste Weise testen. Linting und Mutation Tests für die Code Qualität, Unit Tests um einzelne Funktionalitäten zu testen und End-to-End-Tests (E2E-Tests), die die Anwendung als Gesamtes testen. Dieser Artikel soll zeigen, wie solche E2E-Tests mit Angular aussehen.

Die Beispielanwendung

Die nachfolgende Applikation dient uns als Beispiel, welches wir später automatisiert mit Cypress testen wollen. In dieser Anwendung gibt es ein p-Element mit einer Zahl und einen Knopf, der die Zahl jedes Mal um 1 erhöht, wenn man ihn klickt. Um die Elemente später während der Tests besser identifizieren zu können, geben wir ihnen zusätzlich IDs.

layout.component.html

<p id="counter" class="counter">{{counter}}</p>
<button mat-raised-button id="count-button" color="primary" (click)="clickButton()">Klick mich!</button> 

layout.component.ts

import {Component} from '@angular/core';

@Component({
  selector: 'ox-layout',
  templateUrl: './layout.component.html',
  styleUrls: ['./layout.component.scss']
})
export class LayoutComponent {
  public counter: number = 0;

  public clickButton(): void {
    this.counter++;
  }
} 

Jetzt, wo wir eine Anwendung haben, können wir untersuchen, wie E2E-Tests uns helfen diese Anwendung zu testen.

Konzept von E2E-Tests

E2E-Tests simulieren das Verhalten eines Nutzers, um die Anwendung automatisiert zu testen. Das heißt es werden Klicks und andere Aktionen im Browser durchgeführt. Das hat den Vorteil, dass nicht nur alle Teile der Anwendung einzeln getestet werden, sondern auch die Zusammenarbeit dieser Teile. Mit E2E-Tests testen wir also nicht bloß, ob die Funktion clickButton() den Zähler um eins erhöht und es ein p-Element und ein button-Element gibt, sondern wir testen auch, ob sich nachdem das button-Element geklickt wurde die angezeigte Zahl entsprechend verändert. Somit wird der gesamte Vorgang von Anfang bis Ende getestet. Daher der Name End-to-End.

E2E-Tests schreiben

Im Integration Ordner, den Cypress in unserem Projekt angelegt hat, erstellen wir eine neue Datei "layout-counter.ts". Darin eröffnen wir zunächst mit describe() eine neue Testklasse und mit it() einen Test.

Der Test wird nun wie eine Reihe von Anweisungen für den simulierten Benutzer geschrieben. Zunächst soll der Test die Seite öffnen. Dazu verwenden wir cy.visit(‚/'). Wenn die Seite geladen wurde, soll erst überprüft werden, ob die angezeigt Zahl 0 ist und danach, ob sie sich durch einen Klick auf 1 verändert. Also holen wir uns mit get() die HTML-Elemente. Identifizieren können wir sie anhand der IDs, die wir vergeben haben. Dann soll der Inhalt überprüft werden, geklickt werden und daraufhin ein zweites Mal überprüft werden. Hierdurch kontrollieren wir eine ganze Reihe von Dingen. Zum einen testen wir, ob die Seite besucht werden kann und sie die Zahl anzeigt, die wir im TypeScript Code initialisiert haben. Zum anderen testen wir, ob der Knopf die Funktion clickButton() aufruft, den Zähler erhöht und das p-Element die Änderung anzeigt. Dieser Testablauf stellt also sicher, dass alle wichtige Funktionalitäten der Anwendung funktionieren. Fertig sieht das dann so aus:

layout-counter.ts

describe('[01] Click button', () => {

    it('[01-01] click button once', function () {
        cy.visit('/')
            .get('[id=counter]').should('contain', '0')
            .get('[id=count-button]').click()
            .get('[id=counter]').should('contain', '1');
    });
});
 

 Um sicherzustellen, dass die Zahl um eins erhöht und nicht einfach auf eins gesetzt wird fügen wir einen zweiten Test hinzu, der den Knopf zwei Mal drückt und wonach dementsprechend eine 2 vorfindbar sein sollte. Danach führen wir die Tests aus.

layout-counter.ts

describe('[01] Click button', () => {

    it('[01-01] click button once', function () {
        cy.visit('/')
            .get('[id=counter]').should('contain', '0')
            .get('[id=count-button]').click()
            .get('[id=counter]').should('contain', '1');
    });

    it('[01-02] click button twice', function () {
        cy.visit('/')
            .get('[id=counter]').should('contain', '0')
            .get('[id=count-button]').click()
            .get('[id=count-button]').click()
            .get('[id=counter]').should('contain', '2');
    });
});
 

In der Kommando-Zeile in unserem Projektordner führen wir nun folgende Befehle aus:

npm start
npm run cy-open
 

Daraufhin öffnet sich dieses Menü:

Hier sehen wir direkt unsere Testdatei. Also klicken wir auf sie und Cypress beginnt zu testen.

Wie wir sehen können sind beide Tests erfolgreich, also gibt es keine Fehler. Zum Debuggen können wir uns jeden einzelnen Schritt, den wir in unserem Test definiert haben, in dem Verlauf links anschauen und es wird rechts auf unserer Webseite automatisch angezeigt, wie der Browser zu diesem Zeitpunkt aussah. Besonders bei langen Testfällen und Anwendungen, in denen sich einiges verändert, wie z.B. ein Menü mit vielen Schaltern, ist dieses Feature hilfreich. Es ermöglicht direkte Einsicht in den Zustand des Browsers, wodurch Fehler schnell identifiziert werden können.

Fazit

End-to-End-Tests bieten sich sehr gut als weitere Möglichkeit an, die sicherstellt, dass die gesamte Anwendung funktionstüchtig ist. In unserem Beispiel haben wir mit Hilfe von Cypress in einer einfachen Angular Anwendung das Zusammenspiel von HTML und TypeScript Code getestet. Das lässt sich auch auf größere Anwendungen mit Formularen, mehrere Seiten und vieles Andere ausdehnen. Auch automatisierte Tests in einer CI/CD Pipeline sind mit Cypress möglich und durch die häufigen Updates, die Cypress erhält wird in Zukunft sicher noch mehr möglich sein.

 

Kommentare

Derzeit gibt es keine Kommentare. Schreibe den ersten Kommentar!
Freitag, 29. März 2024

Sicherheitscode (Captcha)

×
Informiert bleiben!

Bei Updates im Blog, informieren wir per E-Mail.

Weitere Artikel in der Kategorie