Blog

Testabdeckung und Performance mit der Testpyramide verbessern

OCT 12, 2018

Die Testpyramide ist eine bewährte Praxis für euren DevOps-Softwareentwicklungsprozess, denn sie ist kosteneffizient, schnell und zuverlässig.

Ramon Medeiros

Ramon Medeiros is working Eficode as a Devops Consultant. He loves coffee and green pipelines, simple as that.

Automatisierte Tests zu schreiben, kann aufgrund der Besonderheiten dieser Art der Programmierung eine Herausforderung sein. Wenn ihr sie in einem DevOps-Prozess für die Softwareentwicklung einsetzen möchtet, der sowohl für Tests als auch für Infrastructure as Code intensiv auf Automatisierung setzt, ist es wichtig, dass die Tests schnell und zuverlässig laufen. Unzuverlässige Tests werden im Google Testing Blog wie folgt definiert: „Flaky Tests sind Tests, die bei demselben Code sowohl ein erfolgreiches als auch ein fehlgeschlagenes Ergebnis liefern“. Solche Tests können eine Pipeline beeinträchtigen, False Positives verursachen und das QA-Team zu falschen Schlussfolgerungen über die Erfolgsquote der Testsuite führen.

UI-Tests orientieren sich am Nutzerverhalten. Damit prüft ihr die Funktionalität der gesamten Software aus Nutzersicht und schafft konkreten geschäftlichen Mehrwert – statt beispielsweise nur zu testen, ob eine Funktion zum Erzeugen von JSON das richtige Format liefert. Das ist der Kernpunkt des Artikels „Just Say No to More End-to-End Tests“ im Google Testing Blog. Er behandelt die praktischen Aspekte von UI-Tests und beschreibt sie als flaky, schwer auf ihre Ursache zurückzuführen und anfällig dafür, kleine Fehler in großen zu verstecken, da die meisten Ausnahmen unterdrückt und in der UI nur benutzerdefinierte Warnungen angezeigt werden.

Um einen Paradigmenwechsel zu erleichtern, stellt Martin Fowler die Testpyramide, vor – eine anschauliche Metapher, die euch dabei hilft, über die verschiedenen Testebenen und die relative Anzahl der Tests pro Ebene nachzudenken. Diese Pyramide wurde erstmals in Mike Cohns Buch „Succeeding with Agile“ erwähnt. Martin merkt jedoch an, dass sie zu stark vereinfacht ist und daher irreführend sein kann.

Schauen wir uns das von Martin aktualisierte moderne Konzept der Testpyramide an:

illustrated automation testing test pyramid image

Die Form der Pyramide veranschaulicht zwei Aspekte dieses Ansatzes: Erstens die richtige Anzahl an Tests pro Ebene – unten gibt es mehr Tests als auf der obersten Ebene. Zweitens zeigt sie den Ressourcenaufwand für die Ausführung jeder Ebene: Unit-Tests am unteren Ende laufen schnell und ohne Drittanbieteranwendungen, während UI-Tests an der Spitze beispielsweise einen Browser und einen Selenium Server nutzen. Die Verteilung der Kategorien entspricht vollständig diesen beiden Kriterien. Schauen wir sie uns genauer an:

  1. Unit-Tests: Sie konzentrieren sich auf das Testen der kleinsten Funktion im Code. Ziel ist es zu überprüfen, ob die Funktion Eingaben korrekt entgegennimmt und wie vorgesehen verarbeitet. Ihr könnt Eingaben mocken oder stubben, damit der Test unabhängig von anderen Komponenten ist.

  2. Komponententests: Sie testen eine vollständige Komponente der Software ohne die UI. Die Komponente ist ein Modul der Anwendung. Auf dieser Ebene prüft der Test erstmals Geschäftsregeln, da alle kleineren Funktionen bereits auf der Ebene der Unit-Tests getestet wurden.

  3. Integrationstests: Sie testen die Kommunikation zwischen zwei Komponenten der Architektur. Ziel ist es zu überprüfen, ob zwei Komponenten miteinander kommunizieren können. Wenn diese Komponenten Informationen aus anderen Teilen des Systems nutzen, etwa APIs oder andere Module, können diese gemockt oder gestubbt werden. Auf dieser Ebene können weitere Tests enthalten sein: Contract Tests, die prüfen, ob eine API ihrem Muster folgt, und Consumer Tests, die prüfen, ob ein Teil des Codes Informationen von anderen APIs konsumieren kann. Auch die Eingabe kann gemockt werden.

  4. End-to-End: Testet die gesamte Software über die UI.

  5. Explorative/manuelle Tests: Manche UI-Tests sind so komplex, dass sie sich nur schwer automatisieren lassen und daher manuell ausgeführt werden können. Zudem lassen sich einige komplexe Abläufe mit Tools erfassen, die Anwendungslogs analysieren, etwa Splunk. Das QA-Team kann diese Abläufe abbilden und Maßnahmen zur Automatisierung eines Tests ergreifen.

  6. Contract Test, der prüft, ob eine API ihrem Muster folgt.

  7. Consumer Test, der prüft, ob ein Teil des Codes Informationen von anderen APIs konsumieren kann. Auch die Eingabe kann gemockt werden.

Unit-Tests lassen sich einfach schreiben und sehr kostengünstig ausführen. Beim Schreiben solltet ihr ausreichend Zeit investieren, um die Funktionalität zu prüfen und folgende Fälle einzugrenzen: Funktioniert die Funktion mit den erwarteten Eingaben, und wie geht sie mit unerwarteten oder ungültigen Eingaben um? Auf der Ebene der Komponententests ist es an der Zeit, die bereits durch Unit-Tests abgedeckten kleinen Funktionen auszublenden und die Geschäftsregeln der Software zu prüfen.

Bei Integrationstests muss die Abdeckung über die erwarteten Fälle in der Kommunikation zwischen Komponenten hinausgehen. Sie sollten Fehlermeldungen von Komponenten verstehen und erkennen können, wann Ausnahmen zurückgegeben werden müssen, die von der Anwendung behandelt werden können. Vergesst nicht, alles zu stubben oder zu mocken, was in diesem Umfang nicht getestet wird. Wenn ihr beispielsweise die Datenbankkommunikation testet, müsst ihr keine echten Drittanbieter-APIs aufrufen.

End-to-End-Tests müssen die wichtigsten Nutzerabläufe in der Anwendung testen. Ihre Anzahl sollte geringer sein als die der vorherigen Tests, da sie bereits einen großen Teil der Anwendung abdecken. Es ist nicht nötig, Tests zu duplizieren.

Abschließend:

Anwendungen ausschließlich mit UI-Tests zu testen, verursacht langfristig hohe Kosten und aufgrund ihrer Flakiness Unsicherheit. Die Testpyramide ist eine gute Praxis für euren DevOps-Prozess in der Softwareentwicklung, da sie kostengünstiger, schnell und zuverlässig ist.

  • Softwareentwicklung
  • DevOps

Subscribe to our newsletter