
Protractor war einst das Mittel der Wahl, um Angular Anwendungen mit einem E2E Test zu versehen. Seit der Version 12 von Angular ist das Framework nicht länger automatisch Bestandteil von Angular CLI Anwendungen und langfristig wird Protractor nicht weiter entwickelt. Stattdessen stehen 3 empfohlene Alternativen in den Startlöchern: Cypress, Nightwatch, und WebdriverIO. Heute werfen wir einen Blick auf „Cypress“.
Cypress einem neuen Projekt hinzuzufügen ist einfach, das Kommando
ng e2e
erkennt in Projekten automatisch, dass keinerlei E2E Konfigurationen vorliegen und installiert und initialisiert nach entsprechender Auswahl eines der drei oben genannten Frameworks. Im Fall von cypress ist das eine Konfigurationsdatei „cypress.config.ts“, einige Basis-Test-Dateien, die im Ordner „cypress“ abgelegt werden und für den Buildprozess eigene Profile in der Datei angular.json (unter anderem das Profil „E2E“ welches vom Kommando ng e2e verwendet werden wird).
Unsere E2E Tests landen in aller Regel im Ordner cypress/e2e und enthalten cy.ts in ihrem Dateinamen, um sie als cypress Test kenntlich zu machen. Innerhalb dieser Dateien implementieren wir nun unsere Prüfungen. Jeder der schon einmal Unit-Tests mit Karma geschrieben hat, wird die grundlegende Struktur der Tests sofort wieder erkennen.
Testsuiten werden mittels describe gebildet, die jeweils ein oder mehrere Lifecyclemethoden beinhalten können (beforeEach) und die einzelnen Testfälle beinhaltet (it)
describe('/user/:id', () => {
const userDetailPO = new UserDetailPO();
beforeEach(() => {
cy.visit('/user/1')
})
it('should show details', () => {
userDetailPO.getUserDetailContent()
.should('contain.text', 'Terry')
.should('contain.text', 'atuny0@sohu.com');
})
it('should enable goto', () => {
userDetailPO.getGoToField()
.type("12");
userDetailPO.getGoToButton()
.should('not.be.disabled')
.click();
cy.url()
.then(href => {
expect(href.endsWith('/user/12')).to.be.true;
});
})
})
export class UserDetailPO {
getUserDetailContent(){
return cy.get('app-user-detail');
}
getGoToButton() {
return cy.get('button[data-cy=go]');
}
getGoToField() {
return cy.get('input[data-cy=user-id]');
}
}
Cypress arbeitet mit Commands, um mit dem Browser zu interagieren (visit), Elemente (auch Subject genannt) zu finden und mit ihnen zu interagieren, wie zum Beispiel get um ein Element auf Basis eine Selektors zu finden (wie jQueries $$), type um Eingaben in Feldern zu simulieren oder click um ein entsprechendes Event auszulösen.
Die eigentlichen Prüfungen erfolgen dann mittels sogenannten Assertions , eine ganze Reihe von Prüfmethoden um unsere Tests zu schreiben. Wichtige Grundidee dabei ist, dass diese Assertions jeweils sogenannte Chainables zurückliefern, auf die weitere Prüfungen implementiert werden können, dabei wird das Subject von einem Aufruf zum nächsten weiter gegeben und kann sich im Zuge der Verwendung auch ändern:
it('should change background if selected', () => {
userPO.getListItem(1) // subject = list item
.should('contain.text', 'Sheldon') // subject = list item
.then( listItem => {
console.log(listItem);
// return listItem; // return current/new subject
})
.should('have.css', 'background') // subject = css-background
.then(bg =>
userPO.getListItem(1)
.click()
.should('not.have.css', 'background', bg)
)
})
All diese Tests lassen sich nun schließlich entweder über die Kommandozeile ausführen
cypress run --browser firefox
oder über die cypress Konsole
ng e2e
Hier haben wir jetzt die Möglichkeit einzelne Suiten auszuwählen (1) und die Tests durchlaufen zu lassen (2). Besonders nett dabei: die einzelnen commands und assertions lassen sich einzeln nachverfolgen und werden entsprechend visualisiert dargestellt (3, markiert den Button, auf den durch dieses command geklickt worden ist)

Wenn Frameworks wie Protractor wegfallen, sorgt das immer für schlechte Stimmung. Schließlich bedeutet das für die Projektteams Umstellungsaufwand. Cypress als Alternative stellt sich zumindest hier sehr benutzerfreundlich auf und überzeugt durch die einfache Konfiguration, Syntax und vor allem interaktive Darstellung der Tests.