Tipps und Tricks für E2E-Tests mit Protractor

Protractor ist installiert, der Test geschrieben, aber die Konsole spuckt nur Fehlermeldungen aus? Hier sind ein paar Tipps, wie verschiedene Funktionalitäten getestet werden können.

Elemente finden

Elemente, mit denen die Nutzer interagieren sollen, können nach verschiedenen Selektoren ausgewählt werden:

  • nach Element-ID
element(by.id('id'))
  • nach HTML-Tag
element(by.tagName('div'))
  • nach CSS-Klasse
element(by.css('.class'))
  • Input-Feld anhand seines Models
element(by.model('profile.firstName'))
  • Button oder Label anhand seines Bindings
element(by.binding('dict.helloWorld'))
  • Ein bestimmtes von mehreren Elementen mit dem gleichen HTML-Tag oder der gleichen CSS-Klasse
element.all(by.tagName('li')).first();
element.all(by.tagName('li')).last();
element.all(by.tagName('li')).get(1);

 

Testen, ob ein Element klickbar ist

Es gibt mehrere Möglichkeiten, zu überprüfen, ob das Element überhaupt da ist:

  • Element (DOM-Knoten) ist vorhanden (aber nicht zwingend sichtbar)
expect(element(by.css('.class')).isPresent()).toBe(true);
  • Element wird angezeigt
expect(element(by.css('.class')).isDisplayed()).toBe(true);
  • Element ist klickbar
expect(element(by.tagName('button')).isEnabled()).toBe(true);

 

Hartnäckig unsichtbare Elemente sichtbar machen

Beispiel: Die select-Optionen bekommen für ein schöneres Layout einen Style “invisible”, bis die Selectbox angeklickt wird. Protractor kann damit nicht umgehen, weshalb ein bisschen getrickst werden muss:

browser.executeScript('return document.getElementsByTagName("select")[0].style.visibility = "visible"').then(function () {});

 

Auf Elemente warten

Soll ein Element angeklickt werden, das erst per Animation eingeblendet wird, gibt es eine Fehlermeldung, wenn zu früh geklickt wurde. Hier kann es sinnvoll sein, den Browser anzuweisen, auf das Ende der Animation zu warten.

browser.wait(element(by.id('id')).isDisplayed()).toBe(true);

mit Timeout:

browser.wait(element(by.id('id'),500).isDisplayed()).toBe(true);

Diese Funktion ist eher buggy. Häufig wird die Fehlermeldung “unimplemented function ‘is pending'” angezeigt. Das kann aber auch ein Hinweis auf einen Fehler im Test sein, z.B. wenn das Element über den verwendeten Selector gar nicht auffindbar ist.

URL vergleichen

Beispiel: Es soll überprüft werden, ob der Klick auf einen Button eine neue Seite öffnet.

element(by.tagName('button')).click().then(function () {
	expect(ptor.getCurrentUrl()).toMatch('#/neue-seite');
})

 

Text vergleichen

Wenn sich der Text eines Elements unter bestimmten Bedingungen ändert, kann er hinterher verglichen werden.

oldButtonName = element(by.tagName('button')).getText();
//Text ändern
newButtonName = element(by.tagName ('button')).getText();
expect(newButtonName).not.toBe(oldButtonName);

 

Formulare ausfüllen

Text-Inputfelder leeren und dann mit „send keys“ ausfüllen:

element(by.model('profile.firstName')).clear();
element(by.model('profile.firstName')).sendKeys('Name');

Date-Input nicht leeren! Datum im Format dd-mm-yyyy eingeben:

element(by.model('profile.birthday')).sendKeys('05-06-1980');

Checkbox anklicken und hinterher das Model auf true oder false testen:

element(by.css('.checkbox')).click().then(function () {
	expect(element(by.model('active'))).toBeTruthy();
});

Erste Option der ersten Selectbox auswählen, wenn es mehrere Selectboxen (Dropdowns) gibt:

element.all(by.tagName('select')).first().element(by.css('option[value="0"]')).click();

 

Länge von Tabellen abfragen

Damit lässt sich z.B. anschließend testen, ob das Anlegen einer weiteren Zeile funktioniert hat.

element.all(by.css('.table tbody tr')).then(function (items) {
	length = items.length;
});

 

Scrollen

Wird kein AngularJS verwendet, kann das Fenster so zu einer bestimmten Position gescrollt werden:

ptor.executeScript('window.scrollTo(0,0);').then(function () {
	page.saveButton.click();
})

Mit AngularJS funktioniert das etwas anders. Hiermit wird das Fenster zu einem bestimmten Element gescrollt:

var scrollIntoView = function (element) {
	arguments[0].scrollIntoView();
};
scrollDown = element(by.binding('dict.helloWorld')).getWebElement();
browser.executeScript(scrollIntoView, scrollDown);

 

Test pausieren

Ein Test kann angehalten oder der Browser daran gehindert werden, sich nach dem Test automatisch zu schließen.

  • Debug-Funktion an der Stelle im Code aufrufen, an der der Test pausieren soll:
browser.debugger();
  • Protractor mit debug-Flag starten
protractor debug protractor.conf.js
  • “c” eintippen, um zu starten oder den Test nach dem Breakpoint fortzusetzen

 

Sicherlich gibt es einfachere Dinge als das Testen von Funktionen mit Hilfe von Oberflächentests. Doch mit Hilfe dieser Tipps und Tricks können zumindest für grundlegende Funktionalitäten nun Tests geschrieben werden, ohne Fehler wie am Fließband zu produzieren.