Testebenen im Projekt

Die Testpyramide zuschneiden: wie viele Tests auf welche Ebene gehören

Die Verteilung ergibt sich aus Laufzeit und Zuordenbarkeit, nicht aus einer Prozentangabe aus einem Buch. Was ihr messt, entscheidet, wo ihr landet.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Seit 1997 am Markt Kleine Gruppen Präsenz und Live-Online Zertifizierte Trainer
Worum es geht

Die Form kippt, und niemand merkt es rechtzeitig

Fast jede Suite beginnt richtig herum und kippt dann langsam. Der Grund ist unspektakulär: Ein Oberflächentest ist die naheliegendste Übersetzung eines manuellen Testfalls. Wer bisher geklickt hat, schreibt auf, was er geklickt hat. So entstehen über zwei Jahre dreihundert Ende-zu-Ende-Tests, eine Handvoll Integrationstests und eine Unit-Ebene, die nur die Bibliotheksfunktionen abdeckt.

Sichtbar wird das erst an zwei Stellen. Die Laufzeit wächst auf eine halbe Stunde, sodass niemand die Suite mehr lokal startet und die Rückmeldung ausschließlich aus der Pipeline kommt. Und ein rotes Ergebnis sagt nicht mehr, wo der Fehler liegt, weil an einem Ende-zu-Ende-Weg zehn Komponenten beteiligt sind. Beides zusammen macht aus der Suite ein Warnsystem, das zwar meldet, aber nicht lokalisiert.

Der dritte Effekt ist der teuerste: Wenn die Zuordnung fehlt, wird jede Ursachensuche zur Detektivarbeit. Ein Team, das für jeden roten Lauf eine halbe Stunde braucht, um überhaupt festzustellen, welche Schicht schuld ist, hört irgendwann auf, genau hinzusehen. Von da an ist die Verteilung der Testebenen kein Stilthema mehr, sondern der Grund, warum niemand mehr auf die Tests hört.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Schritt für Schritt

Der Ablauf, Schritt für Schritt

Sechs Stationen, von der Bestandsaufnahme bis zur regelmäßigen Nachmessung. Die Reihenfolge ist nicht beliebig: Wer verschiebt, bevor er das Risiko kennt, räumt an der falschen Stelle auf.

  1. 1

    Die vorhandene Suite vermessen

    Zähl die Tests je Ebene, miss die Laufzeit je Ebene und erheb die Fehlschlagquote je Test über die letzten Wochen. Wenn eure Suite keine klare Trennung nach Ebenen kennt, ist das schon der erste Befund. Ein grober Zuschnitt reicht für den Anfang: Läuft ein Test ohne Systemstart, mit gestartetem Dienst oder mit Browser und vollständiger Umgebung?

    Geschafft, wenn: Eine Tabelle mit drei Zeilen, aus der hervorgeht, wo die Zeit und wo die Instabilität sitzt.

  2. 2

    Das Risiko kartieren, bevor ihr verschiebt

    Schreib mit dem Fachbereich auf, welche Fehler wirklich wehtun: Geldbeträge, Berechtigungen, Fristen, Datenverlust, rechtliche Pflichten. Diese Liste bestimmt, welche Prüfungen unter keinen Umständen wegfallen dürfen. Sie ist auch die einzige belastbare Antwort auf die Frage, wie viel Abdeckung genug ist, denn ohne sie diskutiert ihr über Prozentzahlen statt über Folgen.

    Geschafft, wenn: Eine priorisierte Liste von Fachbereichen mit der jeweiligen Folge eines unentdeckten Fehlers.

  3. 3

    Die Ebenen für euer System definieren

    Legt schriftlich fest, was bei euch ein Unit-Test, ein Integrationstest und ein Ende-zu-Ende-Test ist, und zwar entlang eurer eigenen Grenzen. Martin Fowler weist zu Recht darauf hin, dass die mittlere Ebene den unklarsten Namen hat und deshalb am häufigsten ausgelassen wird. Nehmt ein Kriterium, das jeder prüfen kann, etwa ob ein Test ohne Netz und ohne laufende Datenbank durchläuft.

    Geschafft, wenn: Eine halbe Seite Definition, an der sich in jedem Review entscheiden lässt, wo ein neuer Test hingehört.

  4. 4

    Von oben nach unten verschieben

    Nimm die teuersten und instabilsten Oberflächentests und frag bei jedem, welche Aussage er eigentlich trifft. Meistens sind es mehrere, und die meisten davon lassen sich eine oder zwei Ebenen tiefer prüfen. Übrig bleibt ein schmaler Rest, der wirklich das Zusammenspiel prüft. Diesen Rest behaltet ihr, alles andere ersetzt ihr, statt es zu löschen.

    Geschafft, wenn: Weniger Ende-zu-Ende-Tests bei gleicher fachlicher Abdeckung und deutlich kürzerer Laufzeit.

  5. 5

    Den Lauf in zwei Stufen aufteilen

    Trenn den schnellen Lauf, der bei jeder Änderung startet, vom langsamen Lauf vor der Auslieferung. Der schnelle Lauf enthält alles, was ohne vollständige Umgebung auskommt, und muss unter der vereinbarten Zeitgrenze bleiben. Der langsame Lauf enthält die Ende-zu-Ende-Wege und die Prüfungen gegen echte Fremdsysteme. Nur der schnelle Lauf blockiert das Zusammenführen von Änderungen.

    Geschafft, wenn: Rückmeldung in Minuten bei jeder Änderung, vollständige Absicherung vor jeder Auslieferung.

  6. 6

    Die Form regelmäßig nachmessen

    Setzt einen festen Termin, etwa einmal im Quartal, an dem ihr die Tabelle aus Schritt eins erneut erhebt und mit der letzten vergleicht. Wichtiger als die absoluten Zahlen ist die Richtung: Wächst die oberste Ebene schneller als die unterste, kippt die Form gerade wieder. Ohne diesen Termin passiert die Nachmessung nie, weil sie nie dringend ist.

    Geschafft, wenn: Eine Zeitreihe, an der ihr Abweichungen erkennt, bevor die Laufzeit sie erzwingt.

Fünf Messpunkte, und die Form wird sichtbar

  1. 01 Wie lange dauert der Lauf, der bei jeder Änderung startet? Über zehn Minuten ist zu lang.
  2. 02 Wie viele Stellen kommen als Ursache infrage, wenn ein Test rot wird? Je weniger, desto besser.
  3. 03 Wie hoch ist die Fehlschlagquote je Ebene? Instabilität sammelt sich fast immer ganz oben.
  4. 04 Welche Ebene hat den letzten echten Fehler zuerst gemeldet? Ebenen ohne Treffer prüfen das Falsche.
  5. 05 Wie oft wird dieselbe Fachregel auf mehreren Ebenen geprüft? Jede Doppelung kostet dauerhaft.
Was du mitnimmst

Woran ihr die Verteilung festmacht

Sechs Kriterien, die sich alle messen lassen. Sie ersetzen die Prozentdiskussion durch Zahlen, die in eurem eigenen Projekt entstehen.

Die Rückmeldezeit als harte Grenze setzen

Der Lauf, der bei jeder Änderung startet, sollte in unter zehn Minuten ein Ergebnis liefern. Das ist die Größenordnung, ab der Entwicklung noch im Zusammenhang der eigenen Änderung ist. Diese Grenze bestimmt die Form der Pyramide stärker als jede Prozentvorgabe, weil sie langsame Tests automatisch nach oben und nach hinten drängt.

Zuordenbarkeit als zweites Kriterium

Frag bei jedem Test, wie viele Stellen als Ursache infrage kommen, wenn er rot wird. Bei einem Unit-Test ist es eine Funktion, bei einem Schnittstellentest eine Komponente, bei einem Ende-zu-Ende-Test der halbe Systemaufbau. Je enger die Antwort, desto mehr Wert hat das rote Ergebnis, und desto weiter unten gehört der Test hin.

Die tiefstmögliche Ebene je Aussage suchen

Für jede Prüfung gilt die gleiche Frage: Lässt sich diese Aussage eine Ebene tiefer treffen? Eine Berechnung gehört in einen Unit-Test, ein Statuscode und eine Nutzlast in einen Schnittstellentest, und der Weg über die Oberfläche prüft nur, ob die Teile miteinander verbunden sind. Diese Regel erklärt den größten Teil der Form.

Doppelungen zwischen den Ebenen aufspüren

Wenn dieselbe Fachregel unten in drei Unit-Tests und oben noch einmal in vier Oberflächentests geprüft wird, zahlt ihr viermal für dieselbe Aussage. Solche Doppelungen entstehen unbemerkt, weil sie in unterschiedlichen Dateien und oft von unterschiedlichen Leuten geschrieben werden. Eine Durchsicht je Fachbereich findet sie zuverlässig.

Nach Ebene messen, wo Fehler gefunden werden

Führt über einige Monate mit, welche Ebene welchen Fehler zuerst gemeldet hat. Wenn eine Ebene selten oder nie als erste anschlägt, prüft sie entweder das Falsche oder das bereits woanders Geprüfte. Diese Zahl ist unbequemer als eine Abdeckungsquote und deutlich aussagekräftiger.

Zwei Läufe statt eines

Ein schneller Lauf bei jeder Änderung mit Unit- und Schnittstellentests, ein langsamerer Lauf mit den wenigen Ende-zu-Ende-Wegen vor der Auslieferung oder nachts. Ohne diese Trennung müsst ihr euch zwischen langsamer Rückmeldung und gestutzter Abdeckung entscheiden, und beide Antworten sind schlecht.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt

Woher die Pyramide kommt und was sie tatsächlich behauptet

Die Darstellung stammt von Mike Cohn und erschien in seinem Buch Succeeding with Agile. Seine ursprünglichen Ebenen hießen Unit Tests, Service Tests und User Interface Tests. Die Aussage war von Anfang an keine Quotenvorgabe, sondern eine Kostenaussage: viele kleine und schnelle Tests unten, einige gröbere in der Mitte, sehr wenige, die das ganze System von außen bedienen.

Google hat für die eigene Arbeit lange eine Orientierung von etwa siebzig Prozent Unit-Tests, zwanzig Prozent Integrationstests und zehn Prozent Ende-zu-Ende-Tests veröffentlicht, zusammen mit einer ausführlichen Begründung, warum zu viele Ende-zu-Ende-Tests langsam sind, häufig instabil werden und im Fehlerfall schwer zuzuordnen sind. Diese Zahlen sind kein Naturgesetz, und für eine Anwendung mit viel Logik im Browser oder für eine reine Datenverarbeitung sehen sie anders aus.

Die Begründung dahinter hält aber jeder Prüfung stand, und sie ist reine Kombinatorik. Ein Ende-zu-Ende-Test bindet Oberfläche, Anwendungslogik, Datenbank, Netz und meist noch ein Fremdsystem ein. Wenn jede dieser Schichten in neunundneunzig von hundert Läufen mitspielt, dann fällt der Gesamttest trotzdem in etwa fünf von hundert Läufen aus einem Grund aus, der mit eurem Code nichts zu tun hat.

Warum die mittlere Ebene der Streitpunkt ist

Martin Fowler benennt in seinem Artikel zur Pyramide genau die Stelle, an der die meisten Teams straucheln: Der Begriff Service Test ist schwer zu greifen, und in der Folge lassen viele Entwicklungsteams diese Ebene schlicht aus. Was übrig bleibt, ist eine Suite mit sehr kleinen und sehr großen Tests und nichts dazwischen, und genau in dieser Lücke sitzen die Fehler, die im Zusammenspiel zweier Komponenten entstehen.

Die Auflösung ist unspektakulär: Definiert die Ebenen an euren eigenen Grenzen, nicht an Lehrbuchbegriffen. Ein brauchbares Kriterium ist die Frage, welche Infrastruktur ein Test braucht. Kein Netz und keine Datenbank ist unten. Eigene Anwendung samt Datenbank, aber ohne Browser und ohne Fremdsysteme, ist die Mitte. Alles zusammen mit echter Oberfläche ist oben. Diese drei Sätze reichen, und sie sind in jedem Review überprüfbar.

Der Nebeneffekt einer klaren Definition ist, dass die mittlere Ebene endlich Kandidaten bekommt. Prüfungen gegen die eigene Schnittstelle, gegen ein Datenbankschema, gegen die Serialisierung eines Nachrichtenformats, gegen die Migrationsskripte: All das ist zu groß für einen Unit-Test und zu klein für einen Ende-zu-Ende-Test, und all das ist wertvoll.

Die Gegenthese und wann sie recht hat

Kent C. Dodds hat der Pyramide die Testing Trophy entgegengestellt, mit einer breiteren Mitte und einer zusätzlichen Grundschicht aus statischer Prüfung, also Typprüfung und Linting. Sein Argument: Mit den heutigen Werkzeugen ist ein Integrationstest im Frontend nicht mehr teuer, und er liefert deutlich mehr Zuversicht als ein Unit-Test für eine einzelne Komponente, die niemand isoliert benutzt.

Für Oberflächen mit viel Zustand im Browser trifft das zu. Wenn eine Komponente nur im Zusammenspiel mit ihrem Zustandsspeicher und ihrem Router überhaupt Sinn ergibt, dann prüft ein isolierter Test vor allem die eigene Nachbildung dieser Umgebung. Auch Fowler weist darauf hin, dass sich Oberflächen mit heutigen Rahmenwerken durchaus auf Unit-Ebene prüfen lassen und die Oberfläche deshalb nicht automatisch ganz oben stehen muss.

Für ein Backend mit Fachlogik gilt die Gegenthese nicht. Eine Preisberechnung mit vierzehn Sonderfällen gehört in vierzehn schnelle Tests direkt an der Funktion und nicht in einen Integrationstest, der jedes Mal eine Datenbank braucht. Die praktische Konsequenz lautet deshalb nicht Pyramide oder Testing Trophy, sondern: Die Form folgt daraus, wo in eurem System die Komplexität sitzt.

Was ihr messt und was ihr besser nicht als Ziel setzt

Vier Zahlen tragen: die Laufzeit des schnellen Laufs, die Fehlschlagquote je Ebene, die Zahl der Testfälle je Ebene und die Frage, welche Ebene den letzten echten Fehler zuerst gemeldet hat. Zusammen ergeben sie ein Bild, das ehrlich ist, weil keine dieser Zahlen sich leicht schönen lässt.

Die Codeabdeckung gehört ausdrücklich nicht in diese Liste, jedenfalls nicht als Zielgröße. Sie sagt, welche Zeilen ausgeführt wurden, nicht welches Verhalten geprüft wurde. Sobald eine Abdeckungsvorgabe zur Kennzahl wird, entstehen Tests, die Code durchlaufen und kaum etwas zusichern. Als Suchwerkzeug bleibt die Abdeckung dagegen nützlich: Ein Blick auf die nicht abgedeckten Stellen zeigt schnell, ob dort etwas Wichtiges liegt.

Die zweite Zahl mit Nebenwirkung ist die absolute Zahl der Testfälle. Mehr Tests sind nicht besser, sie sind erst einmal nur mehr Pflege. Eine Suite, die nach einer Durchsicht dreißig Prozent kleiner ist und dieselben Aussagen trifft, ist eine Verbesserung und sieht in jeder Statistik nach einem Rückschritt aus. Wer diese Zahl berichtet, sollte sie mit der Laufzeit und der Fehlschlagquote zusammen zeigen.

Eine bestehende Suite umbauen, ohne alles anzuhalten

Ein Neubau kommt nicht infrage, denn während der Umbauzeit müsste die Entwicklung weiterlaufen, und niemand bekommt dafür Budget. Der Weg, der funktioniert, ist schrittweise und an die normale Arbeit gekoppelt: Jeder neu gefundene Fehler wird auf der tiefstmöglichen Ebene abgesichert, bevor er behoben wird. Nach einem Jahr wächst die Basis dadurch von selbst, und zwar genau dort, wo es tatsächlich Fehler gibt.

Der zweite Hebel ist die Regel für neue Tests. Ab einem festgelegten Datum entsteht kein neuer Oberflächentest mehr, ohne dass jemand im Review begründet, warum die Aussage nicht eine Ebene tiefer möglich ist. Das ist kein Verbot, sondern eine Begründungspflicht, und sie reicht, um das langsame Kippen aufzuhalten.

Der dritte Hebel ist die Durchsicht der teuersten Bestandstests. Sortier die Ende-zu-Ende-Tests nach Laufzeit und nach Fehlschlagquote und nimm dir jeden Monat die obersten drei vor. Innerhalb eines Jahres ist so der Großteil der schlimmsten Fälle abgearbeitet, und das ohne ein Projekt, das jemand genehmigen muss.

Dazu passende Kurse

Wer die Verfahren kennt, mit denen aus einer Anforderung Fälle entstehen, füllt die Ebenen begründet statt nach Gefühl, und dafür gibt es Kurse zum systematischen Testentwurf .

Die unterste Ebene entsteht dort, wo Code geschrieben wird, deshalb sind Python-Kurse mit Schwerpunkt auf Testcode für viele Teams der ehrlichere Einstieg.

Wissen prüfen

Wie sicher bist du beim Thema wirklich?

Lesen fühlt sich schnell nach Können an. Ein kurzer Test zeigt dir, was davon schon sitzt und wo sich ein Kurs lohnt. Kostenlos, ohne Anmeldung, mit einer Erklärung zu jeder Antwort.

Sehr umfangreicher Überblick über Zusammenhänge und Anwendungsbereiche. Sehr zu empfehlen.
Einführung in die Programmierung für Programmiereinsteiger
Effektives, gemeinsames Erarbeiten der Aufgaben mit vielen praktischen Tipps.
Groovy Grundkurs
Sehr guter Trainer und gute Aufbereitung der Inhalte und auch eingehen auf Fragen der Beteiligten.
Unreal Engine Kurs für Einsteiger

Häufige Fragen

Gilt die Verteilung siebzig zu zwanzig zu zehn für uns?
Als Orientierung ja, als Vorgabe nein. Die Zahlen stammen aus der Praxis von Google und passen zu Systemen mit viel Fachlogik im Backend. Für eine Anwendung, deren Komplexität im Browser sitzt, verschiebt sich das Gewicht in die Mitte. Für eine reine Datenverarbeitung ohne Oberfläche gibt es die obere Ebene fast gar nicht. Nimm die Zahlen als Erwartungshaltung an die Form und leite die tatsächliche Verteilung aus Laufzeit und Zuordenbarkeit ab.
Was zählt bei uns überhaupt als Unit-Test?
Das legt ihr fest, und zwar schriftlich. Ein Kriterium, das sich bewährt hat: Ein Unit-Test läuft ohne Netz, ohne Datenbank, ohne Dateisystem und ohne gestarteten Dienst, und er ist in Millisekunden fertig. Sobald eines dieser Dinge nötig wird, ist es kein Unit-Test mehr, unabhängig davon, wie klein der geprüfte Ausschnitt ist. Der Vorteil dieser Definition ist, dass sie sich technisch prüfen lässt und nicht ausgehandelt werden muss.
Wie viele Ende-zu-Ende-Tests sind zu viele?
Die Grenze liegt dort, wo ihr sie nicht mehr alle bei jeder Auslieferung ausführt oder wo ihr anfangt, rote Ergebnisse zu wiederholen. Als Größenordnung: Die wichtigsten fachlichen Wege eines Produkts lassen sich meist mit einer niedrigen zweistelligen Zahl von Tests abdecken. Wer im dreistelligen Bereich liegt, prüft dort mit hoher Wahrscheinlichkeit Fachlogik, die tiefer besser aufgehoben wäre.
Brauchen wir eine Vorgabe für die Codeabdeckung?
Als Untergrenze für neuen Code kann sie helfen, als Zielgröße schadet sie. Eine Vorgabe von achtzig Prozent für das gesamte Projekt erzeugt Tests, die vorhandenen Code durchlaufen, ohne viel zuzusichern, und in Altbeständen erzeugt sie vor allem Frust. Nützlicher ist die Regel, dass jede Fehlerbehebung von einem Test begleitet wird, der den Fehler ohne die Behebung reproduziert. Diese Regel erzeugt Abdeckung genau dort, wo sie etwas wert ist.
Wo gehören Vertragstests zwischen Diensten hin?
In die Mitte, und sie sind dort einer der wertvollsten Bausteine. Ein Vertragstest prüft, ob eure Schnittstelle die Zusagen einhält, auf die sich ein anderer Dienst verlässt, ohne dass beide Systeme gleichzeitig laufen müssen. Damit ersetzt er eine ganze Reihe von Ende-zu-Ende-Tests, die sonst nur deshalb existieren, weil niemand weiß, ob die Schnittstelle sich geändert hat.
Persönlich für dich da

Deine Ansprechpartner

Du bist dir nicht sicher, welcher Kurs oder welches Level zu dir passt? Wir beraten dich persönlich und kostenlos.

Yves Hoppe

Yves Hoppe

Weiterbildung & Beratung

Hilft dir, aus dem Programmierung-Programm den passenden Kurs für deinen Stand zu finden.

Norbert Jansen

Norbert Jansen

Beratung & Inhouse

Plant mit dir Inhouse-Trainings, die auf eure Abläufe und euren Datenbestand zugeschnitten sind.

Die Ebenen an eurer eigenen Anwendung durchziehen

Wenn der Testentwurf noch wackelt, ist ein Grundlagenkurs zu Testfällen, Fehlermeldungen und Abnahme der schnellere Weg. Wenn die Basis der Pyramide fehlt, hilft ein Kurs zu testgetriebener Entwicklung mit pytest, weil dort genau die unterste Ebene entsteht. Beide gibt es bei cmt offen und inhouse.