Die Testautomationspyramide
Die Testautomationspyramide ist wohl jedem in der Branche ein Begriff. Das Ziel ist eine einfach verständliche Darstellung, wie man die Test-Prioritäten in einem Software-Projekt prinzipiell verteilen sollte. Die einfachste Darstellung ist eine Pyramide mit 3 Ebenen, doch bereits bei den einfachsten Abbildungen gibt es unterschiedliche Ausprägungen und (missverständlich) verwendete Begrifflichkeiten:
Abbildung 1: (Quelle: anymindgroup.com/news/tech-blog/15053)
Abbildung 2: Die Testpyramide von Mike Cohn (Quelle: www.openknowledge.de/blog/die-testpyramide)
Abbildung 3: (Quelle: betterprogramming.pub/the-test-pyramid-80d77535573)
Sind „System-Tests“ und „E2E“ Tests eigentlich dasselbe? Genau genommen sind sie das nicht (Quelle ISTQB), auch wenn das in der Praxis weniger unterschieden wird. „UI“ beschreibt eine Interaktionsmöglichkeit und weniger einen Umfang oder Scope. Und trotzdem werden diese unterschiedlichen Begriffe oft gleichbedeutend verwendet.
Im Laufe der Zeit haben sich davon etliche Abwandlungen und Erweiterungen gebildet: Die traditionellen 3 Ebenen wurden zum Teil unterteilt (Integration wurde z.B. zu API, Integration und Component) oder durch zusätzliche Ebenen erweitert oder ein Wölkchen auf der Spitze platziert und damit eigentlich eine „Testpyramide“ geschaffen (die Wolke steht für manuelle Tests).
Abbildung 4: (Quelle: de.parasoft.com/blog/how-to-enable-quality-at-speed-in-5-steps/)
Abbildung 5: (Quelle: www.browserstack.com/guide/testing-pyramid-for-test-automation)
Eine weitere Darstellung ist die 3-dimensionale Pyramide („extended test pyramid“), die zusätzliche Informationen zu den einzelnen Ebenen bieten möchte, wie z.B. welche non-functional Requirements in den einzelnen Ebenen fokussiert werden sollten, in welcher Testumgebung die Tests der jeweiligen Ebene durchgeführt werden sollten, oder wer für Testfälle verantwortlich ist.
Abbildung 6: Erweiterung um zwei Dimensionen mit zusätzlichem Informationsgehalt (Quelle: leaddev.com/agile-other-ways-working/demystifying-software-engineering-test-pyramid)
Wieso eigentlich eine Pyramide?
Die Pyramidenform ist natürlich kein Zufall und steht für „unten ist irgendetwas mehr als oben“. Wovon genau es „mehr“ gibt, ist allerdings unklar, weil es auch hier wieder unterschiedliche Interpretationen gibt:
- * Die Anzahl der Testfälle unten ist höher als oben
- * Die Ausführung der Testfälle ist unten einfacher und schneller als oben (Stichwort „Immediate Feedback“)
- * Der Aufwand, Testfälle zu erstellen, ist unten geringer als oben
- * Die Stabilität der Testfälle ist unten höher als oben (mit dem Wartungsaufwand verhält es sich dann genau umgekehrt)
- * …
Damit ergibt sich auch eine weitere Aussage, die sich aus der Form der Pyramide ergibt: Die unteren, breiteren Ebenen sind enorm wichtig für die Stabilität der Pyramide! Legt man zu wenig Wert auf die Basis, beginnt die Pyramide zu wackeln oder bricht in sich zusammen. Das ist natürlich wieder eine Metapher für die Qualität im Software-Projekt.
Wieso bilden Unit-Tests das Fundament?
Unit Tests haben einige wesentliche Eigenschaften, die sie für das Fundament eines Software-Projekts unersetzlich machen:
- * Stabilität: Ein Unit-Test (vorausgesetzt, er ist richtig geschrieben), ist stabil – Punkt. Ein Test über die UI kann noch so „richtig“ geschrieben sein – er wird trotzdem niemals die Stabilität eines Unit-Tests erreichen: Die Einflussfaktoren auf einen Test über die UI sind enorm und jede kleine Abweichung kann die erfolgreiche Durchführung verhindern.
- * Durchlaufzeit: Die Abarbeitung von Codetests ist schnell – viel schneller als es Tests über externe Schnittstellen oder gar die UI jemals sein könnten.
- * Auf einfache Weise komplexe Szenarien testen: Eine Grundvoraussetzung für Unit-Tests ist der Einsatz von Mocking-Frameworks. Darüber allein könnte man lange Artikel schreiben, deswegen nur kurz: Mit Mocking-Frameworks ersetzt man Abhängigkeiten durch sogenannte Mocks, also Platzhalter, die auf bestimmte Anfragen mit vordefinierten Antworten reagieren. Damit ist es möglich, die zu testende Unit in den unterschiedlichsten Ausprägungen zu testen, die ohne Mocking nur sehr schwer und mit viel Aufwand herzustellen wären.
- * Besseres Software-Design: Wenn man sich beim Schreiben von Unit-Tests buchstäblich die Finger bricht und Kopfschmerzen bekommt, ist die Ursache meist eine schlechte Architektur der zu testenden Units. Dies sollte als wichtiger Trigger für ein Design Review dienen. Dem kann man mit Test-Driven-Development bereits von Beginn an aktiv vorbeugen.
- * …
Die Liste kann man problemlos mit weiteren Gründen weiterführen, wieso Unit-Tests zu Recht die Basis einer guten und effizienten Testautomationsstrategie sein müssen.
Wieso dann nicht nur Unit-Tests?
Trotz der vielen Vorteile und positiven Eigenschaften von Unit-Tests reichen sie für sich allein nicht aus. Es ist zwingend notwendig, die oberen Ebenen der Pyramide ebenfalls zu berücksichtigen. Ein System besteht nunmal aus mehreren Teilen (Komponenten, Schichten oder Systemen), die irgendwann miteinander über Schnittstellen kommunizieren müssen. Und natürlich ist die UI als Interaktionsschicht für den Endbenutzer enorm wichtig und muss dementsprechend qualitätsgesichert werden.
Aber wenn man UI-Tests sowieso machen sollte, dann reicht das doch theoretisch aus, denn nichts ist realer am produktiven Einsatz und näher am Endbenutzer als die UI, oder?
Ein gängiges Anti-Pattern: Der Ice Cream Cone
Theoretisch lässt sich allein mittels Testfällen über die UI dieselbe Abdeckung erreichen wie mit der Kombination aus allen 3 Ebenen der Testautomationspyramide (wenn wir davon ausgehen, dass über die UI alle Funktionen zur Verfügung stehen).
Abbildung 7: Das gängigste Anti-Pattern: Ice Cream Cone (Quelle: saeedgatson.com/the-software-testing-ice-cream-cone/)
In der Theorie hat sich daraus das Anti-Pattern namens „Ice Cream Cone“ (in Österreich würden wir dazu „Eis-Stanitzel“ sagen, für unsere Deutschen Kollegen müsste „Eiswaffel“ passen) entwickelt: Die Testautomationspyramide steht auf dem Kopf, der Fokus liegt auf der Testautomation über die UI und ist garniert mit einer großen Anzahl von manuellen Tests. Dieses Anti-Pattern ist in vielen Software-Projekten trauriger Alltag. Meistens fehlen dann die unteren Ebenen „Unit“ und „Integration“ gleich zur Gänze, die so wichtige Basis ist also gar nicht vorhanden. Auch wenn das aus Abdeckungssicht wie erwähnt an sich möglich ist, gehen dabei die Vorteile der unteren Ebenen gänzlich verloren (Stabilität, Wartungsaufwand, Durchlaufzeit, …), die Pyramide wackelt, die Qualität des Software-Projekts ist nachhaltig in Gefahr.
Die Ursachen, wieso es in der Praxis immer wieder zu diesem Effekt kommt, sind einfach: Entwickler wollen nicht testen und Tester können nicht entwickeln (etwas überspitzt formuliert natürlich) und es gibt niemanden, der dieses Gefüge aufzubrechen versucht. Die Tester versuchen dann, mit den üblichen Testautomationswerkzeugen alle Anforderungen automatisiert abzudecken. Wenn das aus Zeitmangel nicht mehr funktioniert, steigt die Anzahl an manuellen Testfällen. Neue Funktionalitäten brauchen mehr Zeit im Test, Regressionstests dauern immer länger oder der Umfang wird gekürzt, Fehler häufen sich.
Ein neues Anti-Pattern entsteht: Die Testautomation Cloud
Auch wenn der „Ice Cream Cone“ immer noch häufig anzutreffen ist, gibt es immer mehr Software-Projekte, die versuchen, die Testautomationspyramide zu berücksichtigen. Ein wichtiger Aspekt, den die Testautomationspyramide aber nicht beschreibt, ist die inhaltliche Dimension der Testfälle: Die Ebenen existieren nicht lose nebeneinander, sondern müssen inhaltlich abgestimmt sein. Ziel muss es sein, Testinhalte in den oberen Ebenen einzusparen, weil sie in den unteren Ebenen bereits hinreichend abgedeckt wurden, oder bewusst sehr wichtige Anforderungen auf mehreren Ebenen abzudecken.
Ein einfaches Beispiel: Das Passwortfeld soll prüfen, ob das neue Passwort allen Regeln entspricht. Sinnvoll ist es, auf Unit-Test Ebene alle Regeln zu testen und über die UI nur noch stellvertretend einen Fehlerfall, und natürlich den Gutfall mit einem regelkonformen Passwort.
Obwohl das eben ein sehr einfaches Beispiel ist, wird schnell klar: es geht nicht ohne Kommunikation. Nur wenn klar ist, welche Anforderungen in welcher Ebene abgedeckt sind, kann man diese Synergien nutzen und auf oberen Ebenen bestimmte Testfälle weglassen. Das hört sich jetzt nach „no na“ an, aber oft sind Entwickler und Tester immer noch organisatorisch und räumlich voneinander getrennt. Die Kommunikation zwischen diesen beiden Teams passiert also nicht einfach von selbst, sondern muss gefordert und gefördert werden. Fehlt diese Kommunikation, werden im best case dieselben Testfälle auf verschiedenen Ebenen umgesetzt, im worst case verlässt sich die obere Ebene auf die untere und gefährliche Testlücken entstehen. Die einzelnen Ebenen sind nicht mehr aufeinander aufbauend, sondern fliegen lose herum, und überschneiden sich noch durch Zufall: das Anti-Pattern „Testautomation Cloud“ (© Klemens Loschy)
Abbildung 8: Das neue Anti Pattern, wenn der Ice Cream Cone erfolgreich beseitigt, wurde: Die Testautomation Cloud (Quelle: SEQIS GmbH)
Auch wenn eine funktionierende Kommunikation das A und O ist, ohne das nichts funktioniert, ist der nächste Schritt die toolunterstützte Anforderungsabdeckung. Tools wie z.B. Xray (ein im Test-Bereich weit verbreitetes Jira Plugin) helfen, den Überblick zu bewahren, welche Anforderungen durch welche Tests abgedeckt sind. Die Integration von Xray mit Unit-Test Frameworks, Testautomationstframeworks und -tools ist möglich und konnte von uns in einigen Projekt bereits erfolgreich umgesetzt werden. Dadurch wird die Abdeckung automatisch bei der Testdurchführung aktualisiert und die manuelle Wartung entfällt komplett, was gerade bei mehreren 100 Unit-Tests nicht mehr manuell möglich wäre.
A fool with a tool is still a fool
Das Pattern der Testautomationspyramide ist nichts anderes als ein weiteres Tool im Toolkit eines Software-Projektes. Und wie jedes Tool ist der richtige Einsatz maßgeblich für den Erfolg verantwortlich. Eine besondere Herausforderung ist, dass das Pattern überhaupt nur dann funktionieren kann, wenn die Kommunikation aller Beteiligten gegeben ist und über alle Fachkompetenzen hinweg Vertrauen herrscht. Wir verlassen uns im Projektalltag meist auf formale Prozesse, strenge Regeln und klobige Tools und vergessen darauf, dass sich alles um die Menschen dreht und wir viel mehr darauf achten müssen, dass wir ein Arbeitsumfeld schaffen, welches das Miteinander fördert und die Kompetenzen stärkt. Mit einem gut eingespielten Team sind formale Prozesse obsolet, es funktioniert quasi von selbst. Umgekehrt rettet kein Prozess der Welt eine Sammlung loser Individuen.
Klemens Loschy
klemens.loschy@seqis.com
ist Principal Consultant bei SEQIS. Er kann auf jahrelange Erfahrung in den unterschiedlichsten Bereichen zurückblicken. Durch sein hohes Interesse an Test- und Softwareentwicklung kann er stets die neuesten Erkenntnisse in seine Projekte miteinbeziehen. Er arbeitet im Team razzfazz.io, der neuen Marke von SEQIS für individuelle Softwareentwicklung.