Menschen von oben fotografiert, die an einem Tisch sitzen.

adesso Blog

Zunächst fing alles damit an, dass sich unser Testmanager zu Beginn des Projektes beklagte, er habe zu wenig Kapazitäten, um alle geplanten Funktionen der Software, die für das erste Release vorgesehen waren, vollumfänglich durchzutesten. Nun ist es natürlich so, dass sich Testmanager eigentlich fast immer über mangelnde Unterstützung beklagen. In diesem Fall mussten wir ihm - angesichts einer halben Person in der Tester-Rolle, plus dem Testmanager selber – jedoch Recht geben.

Sein Ansinnen, die Entwicklerinnen und Entwickler sollten, orchestriert durch liebevoll aufgebaute HP ALM Testpläne, die Applikation händisch durchklicken, mussten wir jedoch zurückweisen. Schließlich sollte der Code pünktlich geliefert und so viele der Stories im prall gefüllten Backlog wie möglich umgesetzt werden. Aus dieser Not geboren, beschlossen wir einen Kompromiss: Die Entwicklerinnen und Entwickler sollten die meisten der Testfälle über die UI automatisieren. Der Rest sollte von den anderthalb Testern manuell durchgeführt werden.

Da es sich bei unserem Projekt um eine Webapplikation handelte, musste ein Framework her, das:

  • unterschiedliche Browser fernsteuern konnte,
  • automatisiert im Batch funktionierte,
  • die Testfälle in einer Sprache beschrieb, die es erlaubte, die Testschritte aus HP ALM Stück für Stück nachzubauen und diese auch später wiederzuerkennen und
  • keine Lizenzgebühren nach sich ziehen durfte.

Die Wahl fiel auf eine Kombination aus den beiden Open-Source-Komponenten Cucumber und Selenium, die wir im Folgenden beschreiben wollen. Zunächst ein Beispiel.

Einführendes Beispiel

In jedem Maven-basierten Cucumber-Projekt findet sich unter „resources“ ein einzelnes Verzeichnis in der Wurzel des Projekts mit dem Namen "features". Dort werden alle Cucumber-Features gespeichert. Eine Feature-Datei enthält eine Beschreibung des Testszenarios auf hoher Ebene in einfacher Sprache. Diese einfache Textsprache ist als Gherkin bekannt. Gherkin unterstützt neben dem Standard „Englisch“ noch viele weitere Sprachen. In unserem Projekt wurde als Sprache „Deutsch“ gewählt, um möglichst nah an der Vorlage aus HP ALM zu bleiben.

@TestForLogin

Szenariogrundriss: Erfolgreicher Campus Login

Angenommen Ich befinde mich auf der Campus Page

Und Ich als Anmeldedaten "<email>" und "<Passwort>" eingebe

Und Ich den Button "Anmelden" klicke

Dann Sehe ich die Hauptseite von der Campus Page mit dem Willkommenstext

Beispiele:

| email | Passwort |

| a.user@example.com | FOO! |

| b.user@example.com | BAR! |

Hier eine kurze Beschreibung der Komponenten:

Tag(s): Optional kann ein Szenario oder ein Szenariogrundriss getaggt werden, wie hier mit „@TestForLogin“. Beim Starten der Testsuite können optional Tags übergeben werden, um gezielt Teile der Szenarien auszuführen oder auszuschließen.

Szenario oder Szenariogrundriss (Scenario oder Scenario Template): Ein Szenario beschreibt die Schritte und das erwartete Ergebnis für einen bestimmten Testfall. Wird der „Szenariogrundriss“ gewählt, besteht die Möglichkeit, mit Hilfe von Datentabellen, das Szenario zu parametrisieren und damit mehrfach auszuführen. In unserem Beispiel wurde das Szenario zweimal durchlaufen und das Login für den Benutzer a.user@example.com und für den Benutzer b.user@example.com getestet.

Angenommen (Given): Sie gibt den Kontext des auszuführenden Textes an.

Wenn (When): spezifiziert die auszuführende Testaktion

Und (And): Diese Komponente spezifiziert eine weitere Testaktion

Dann (Then): Das erwartete Ergebnis des Tests kann durch "Then" dargestellt werden.

Beispiele: Dieses Schlüsselwort ist etwas unglücklich gewählt, handelt es sich doch hierbei um die Parameter für einen Szenariogrundriss, der zur Laufzeit eingesetzt wird.

Die Schlüsselworte „Angenommen“, „Wenn“, „Und“, „Dann“ können beliebig oft und in beliebiger Reihenfolge in einem Szenario auftauchen.

Wie ihr seht, sind die Features auf Grund der Teilsätze in Umgangssprache auch für Nicht-Developer leicht lesbar und auch schreibbar. Eine Arbeitsteilung, die ihr euch hier vorstellen könnt, ist die Bereitstellung der Szenariogrundrisse durch einen Developer und die Parametrisierung in der „Beispiele“-Sektion durch ein Testteam oder einen Businessanalysten.

Architekturbeschreibung

Bevor wir zum Java Code des Beispiels kommen, möchten wir euch zeigen, wie die einzelnen Code-Teile zusammenspielen.


Zusammenspiel der Code-Teile in einem Sequenzdiagramm

In diesem Sequenzdiagramm wird folgendes erkennbar:

  • Der TestRunner sucht sich sämtliche Feature-Files im definierten Resourcenpfad (eventuell eingeschränkt durch Tags) und führt die enthaltenen Steps aus.
  • Der Prosa-Ausruck eines Gherkin Step muss zu einem annotierten Test matchen.
  • Ein Test verwendet eines oder mehrere Page Objects, welche das Java Pendant zu den HTML-Seiten der Anwendung darstellen.
  • In den Page Objects kommt Selenium zum Einsatz, um den Browser über seinen jeweiligen Webdriver anzusprechen.
Vervollständigung des Beispiels

Um das genannte Beispiel zu vervollständigen, zeigen wir euch noch den Java Code für die Tests und Page-Objekte:

Java Code Testklasse

	
		@Given("^Ich befinde mich auf der Adesso Page für Site \"(.*)\"$")
		public void onLandingPage(String site) {
		  	goToCampusSite(site)
		}
		@And("Ich als Anmeldedaten \"(.*)\" und \"(.*)\" eingebe$")
		public void enterCredentials(String email, String passwort) {
		landingPageHeader landingPageHeader = new LandingPageHeader(driver);
		landingPageHeader.enterEmail(email);
		landingPageHeader.enterPasswort(passwort);
		}
		@And("^Ich den Button \"Anmelden\" klicke$")
		public void clickAnmeldenLink() {
		landingPageHeader landeingPageHeader = new LandingPageHeader(driver);
		landingPageHeader.clickLogin();
		}
		@Then("^Sehe ich die Hauptseite von der Campus Page mit dem Willkommenstext $")
		public void checkTheCampusSite(){
		campus campusPage = new CampusPage(driver);
		Assert.assertNotNull(campusPage.getWelcomeTextString());
		}
	

Die Methoden und die Parameter sind in Englisch gehalten, weil der Code mit hoher Wahrscheinlichkeit in einem internationalen Team weiterentwickelt werden wird. Die Gherkin Annotationparameter sind auf Deutsch, wegen der deutschen Szenarien. Man sieht sehr schön, wie die Halbsätze der Steps in den Szenarien zu den Annotationen passen und die Platzhalter für die Parameter mit regulären Ausdrücken definiert werden können.

Wir haben es uns zur Regel gemacht, jede Annotation immer mit einem "^" (Match Anfang der Zeile) zu beginnen und mit einem "$" (Match Ende der Zeile) zu beenden, damit die Eindeutigkeit des Matchings eines Steps besser gewährleistet ist.

Die "@Then" Methode sollte immer mindestens ein Assert haben.

Java Code Page Object

	
		public class LoginPage extends AbstractPage {
		  @WebElementLink(how = How.ID, using = "usernameInput");
		 private WebElement email;
		 @WebElementLink(how = How.ID, using = "passwortInput");
		 private WebElement passwort;
		 @WebElementLink(how = How.ID, using = "submitButton");
		 public LoginPage(WebDriver driver){
		 super(driver);
		 }
		 public void fillCredentials(String EmailString, String passwortString) {
		 fillBox(email, emailString);
		 fillBox(passwort, passwortString);
		 }
		 public void clickLogin() {
		 click(loginButton);
		 }
		}
	

Jede Klasse erbt von einer AbstractPage, die wir selber geschrieben haben und in der viele nützliche Methoden - etwa das Befüllen von Textfeldern oder das Klicken auf Objekte im HTML DOM - versteckt sind.

Fazit

Wir hoffen, dass wir euch in unserem Blog-Beitrag einfach und verständlich zeigen konnten, wie man durch den Einsatz von automatisierten UI-Tests den manuellen Aufwand für End-To-End Tests - insbesondere vor dem Release - signifikant reduzieren kann. Durch die Verwendung des PageObject-Patterns ergibt sich ein hoher Grad an Wiederwertbarkeit und Wartbarkeit.

Natürlich müssen auch einige Dinge beachtet werden, um mit einer solchen Testsuite den gewünschten Nutzen zu erzielen:

  • Die Testsuite sollte auf jeden Fall regelmäßig laufen, denn ansonsten seid ihr kurz vor der Abgabe eines Inkrementes (aka „Sprintende“) damit beschäftigt, viele Tests zu reparieren, die durch Umbauten kaputt gegangen sind.
  • Wo immer es geht, solltet ihr keine Style-Klassen als Selektoren benutzen, sondern möglichst eigene HTML-Attribute wie in unseren Beispielen die „data-testing-id“.
  • Die der Applikation zu Grunde liegende Testdatenbank muss stabil bleiben oder darf sich nur ändern, wenn zeitgleich die erwarteten Werte in den feature files mitgezogen werden.

Insgesamt kann man sagen, dass die Nutzung von Cucumber und Selenium als Basis für unsere Testsuite einiges an Resourcen gespart und tatsächlich auch Fehler gefunden hat, die man sonst vielleicht nicht so rasch entdeckt hätte. Unser Testmanager zumindest war glücklich – was will man mehr?

Ihr möchtet mehr zu spannenden Themen aus der adesso-Welt erfahren? Dann werft auch einen Blick in unsere bisher erschienen Blog-Beiträge.

Bild Thomas  Schumacher

Autor Thomas Schumacher

Thomas Schumacher ist Senior Software Architekt bei adesso. Sein Fokus liegt auf Java-Technologien und Microservices. Daneben beschäftigt er sich mit den Themen Clean Code, Design Patterns, Cloud und agilen Vorgehensmodellen.

Bild Iro Kargiou

Autorin Iro Kargiou

Iro Kargiou ist als Java-Trainee im Banking-Bereich bei adesso in Frankfurt am Main tätig. Sie fokussiert auf Java-Technologien.

Diese Seite speichern. Diese Seite entfernen.