Start / Seminare / Java Testing mit JUnit, Mockito und Testcontainers
Modul
Eine tragfähige Teststrategie entwickeln
4 Kapitel in diesem Modul-Video · Laufzeit
Transkript
Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.
Eine tragfähige Teststrategie entwickeln
0:00 Willkommen zu drei Tagen Java Testing. Wir sprechen über JUnit, über Mockito und über Testcontainers — aber wir fangen bewusst mit keinem der drei an. Denn Werkzeuge zu bedienen ist die kleinere Hälfte der Aufgabe. Die größere ist die Frage, welche Tests eine Anwendung überhaupt braucht. Fast jedes Projekt, das ich kenne, hat Tests. Deutlich weniger Projekte können sagen, welchen Fehler welcher Test verhindern soll.
0:25 Genau diese Lücke schließen wir in diesem ersten Modul. Am Ende steht eine Landkarte für unser Beispielprojekt, und die begleitet uns durch alle zwölf Module.
Eine tragfähige Teststrategie entwickeln
0:35 Der erste Tag gehört JUnit. Wir klären zuerst die Strategie, richten dann JUnit 6 ein, schreiben verständliche Tests, machen aus wiederkehrenden Fällen Datensätze und nehmen am Abend Lifecycle, Extensions und parallele Ausführung dazu. Alles, was heute entsteht, tragen wir morgen weiter, wenn Mockito dazukommt.
Ziele automatisierter Tests und ihre Ebenen
0:55 Beginnen wir mit der Frage, die selten gestellt wird: Wozu ist der Test eigentlich da? Es gibt zwei Antworten, und die zweite ist die wichtigere — auch wenn fast alle die erste nennen. Die naheliegende Antwort lautet: Tests finden Fehler. Das stimmt, aber es ist die schwächere Begründung. Die stärkere lautet: Tests machen Änderungen möglich.
1:16 Stellen Sie sich zwei Handwerker auf einem Dach vor. Der eine trägt ein Seil, der andere nicht. Beide arbeiten gleich gut — aber nur einer traut sich an die Kante. Genau das leistet eine Testsuite. Wer refaktorieren kann, ohne zu hoffen, verändert eine Anwendung anders als jemand, der bei jedem Umbau die Luft anhält. Und weil Tests auf verschiedenen Ebenen sehr Verschiedenes leisten, lohnt der Blick auf diese Ebenen.
1:42 Diese vier Schichten sind kein Organigramm, sondern vier verschiedene Fragen an dieselbe Anwendung. Ganz unten fragt der Unit-Test: Rechnet diese eine Regel richtig? Eine Schicht darüber prüft der Komponententest, ob ein Baustein seinen Vertrag hält. Der Integrationstest fragt, ob Anwendung und Infrastruktur wirklich zusammenpassen — Schema, Mapping, Transaktionen.
2:04 Und ganz oben prüft der End-to-End-Test, ob der Weg durch das Ganze funktioniert. Je weiter oben, desto realistischer die Antwort und desto langsamer und ungenauer die Diagnose. Der Trick besteht darin, jede Frage auf der Ebene zu stellen, die sie am billigsten beantwortet. Interessant an dieser Tabelle ist nicht die linke Spalte, sondern die rechte. Jede Ebene hat einen blinden Fleck, und den kennen die wenigsten Teams.
2:30 Der Unit-Test sieht die falsche Verdrahtung nicht, weil er sie selbst herstellt. Der Komponententest sieht kein echtes SQL, weil er die Datenbank ersetzt hat. Und der End-to-End-Test sieht zwar den kaputten Gesamtweg, sagt Ihnen aber nicht, wo er kaputt ist — er meldet einen roten Bildschirm, keine Zeile. Wer diese blinden Flecken kennt, verteilt Tests nicht mehr nach Gewohnheit, sondern nach dem, was jede Ebene tatsächlich sehen kann.
2:55 Diese Unterscheidung klingt akademisch und hat sehr praktische Folgen. Ein fachlicher Testfall kommt aus der Domäne: Ab zehn Kisten gilt der Staffelpreis. Diese Regel überlebt jedes Refactoring, weil sie nichts über den Code aussagt. Ein technischer Testfall kommt aus der Umsetzung: Diese Methode ruft jene Methode auf. Er stirbt, sobald jemand die Umsetzung ändert — und dann steht das Team vor einem roten Test und weiß nicht, ob die Regel gebrochen ist oder nur der Weg dorthin.
3:23 Beides hat seinen Platz. Aber sie gehören auseinandergehalten, sonst wird jedes Refactoring zur Untersuchung. Der erste Punkt ist der häufigste, und er passiert unauffällig: Ein Fehler taucht auf, jemand schreibt einen Test dagegen — und zwar dort, wo der Fehler zufällig auffiel. Nach zwei Jahren ist die Verteilung reine Historie. Der zweite Punkt kostet Laufzeit: Rechenregeln über End-to-End-Tests abzusichern dauert Minuten statt Millisekunden.
3:51 Der dritte ist eine Kennzahlenfalle — die Zahl der Tests sagt nichts über ihre Aussage. Und der vierte ist der subtilste: Wer Tests nach Klassen schneidet, bindet die Struktur. Wer nach Verhalten schneidet, bindet die Fachlichkeit. Nur die Fachlichkeit soll halten.
Testmodelle und ihre Abwägungen
4:07 Wenn die Ebenen klar sind, kommt die nächste Frage: Wie viel von welcher Ebene? Dazu gibt es Modelle, und sie widersprechen sich. Sehen wir uns an, warum das kein Streit ist, sondern eine Abwägung. Die Testpyramide ist das bekannteste Bild: viele schnelle Tests unten, wenige langsame oben. Sie stammt aus einer Zeit, in der ein Integrationstest bedeutete, eine Testumgebung zu buchen.
4:31 Inzwischen gibt es Alternativen — die Testing Trophy legt den Schwerpunkt auf Integrationstests, die Honeycomb auf Komponententests. Alle drei beantworten aber dieselbe Frage: Wo bekomme ich die meiste Sicherheit je Minute Laufzeit? Und weil Container den Preis für Realismus deutlich gesenkt haben, fällt die Antwort heute anders aus als vor zehn Jahren.
4:52 Kein Modell ist falsch, aber jedes hat eine Annahme über Kosten, die man prüfen sollte. Diese Gegenüberstellung zeigt den eigentlichen Tausch. Links, mit vielen Unit-Tests, bekommen Sie das Ergebnis in Sekunden — aber Sie prüfen Regeln, nicht Verdrahtung, und die Tests brechen bei jedem Refactoring. Rechts, mit vielen Integrationstests, warten Sie Minuten — dafür bricht der Test erst, wenn wirklich die Fachlichkeit bricht.
5:17 Beide Spalten haben eine Voraussetzung, und die steht in der letzten Zeile: Links brauchen Sie saubere Schnitte in der Anwendung, rechts reproduzierbare Umgebungen. Fehlt die jeweilige Voraussetzung, funktioniert die Spalte nicht — dann hilft auch das schönste Modell nicht weiter. Es gibt hier keine Lösung, nur eine bewusste Entscheidung. Je realistischer die Umgebung, desto später die Rückmeldung.
5:40 Je schneller die Rückmeldung, desto mehr Annahmen stecken im Test — und jede Annahme kann still veralten. Testcontainers hat diesen Tausch verschoben, aber nicht aufgehoben: Eine echte Datenbank startet in Sekunden statt in Stunden, sie startet aber immer noch. Wo die richtige Mischung liegt, hängt am Risiko der Anwendung.
5:59 Ein Buchhaltungssystem und eine interne Auswertung verdienen nicht dieselbe Verteilung, auch wenn im Lehrbuch dieselbe Pyramide steht. Die interessanteste Spalte ist nicht die Laufzeit, sondern die Pflege. Laufzeit können Sie kaufen — mit einem größeren Build-Agenten, mit Parallelität, mit Caching. Pflegeaufwand können Sie nicht kaufen.
6:19 Ein End-to-End-Test, der jede Woche aus einem anderen Grund rot wird, verbraucht Aufmerksamkeit, und Aufmerksamkeit ist die knappste Ressource im Team. Deshalb sterben End-to-End-Tests in der Praxis nicht an ihrer Laufzeit, sondern daran, dass niemand sie mehr repariert. Wer diese Spalte bei der Planung mitliest, baut eine Suite, die auch in zwei Jahren noch läuft.
6:41 Der erste Punkt begegnet mir oft: Die Pyramide wird als Quote verordnet — siebzig Prozent Unit-Tests — ohne dass jemand das Risiko der Anwendung angesehen hat. Der zweite ist die stille Kapitulation: Langsame Tests werden nicht schneller gemacht, sondern aus der Pipeline genommen, meist in einen nächtlichen Lauf, den niemand liest.
7:00 Der dritte ist harmlos gemeint und teuer: Ein Modell wird gewechselt, weil ein Vortrag überzeugt hat. Und der vierte ist die Frage, die kaum jemand stellt: Welche Testart hat im letzten Jahr tatsächlich Fehler gefunden? Die Antwort überrascht fast immer.
Eine projektspezifische Teststrategie festlegen
7:15 Jetzt wird es konkret. Aus Ebenen und Modellen wird eine Entscheidung für dieses eine Projekt — und die passt auf eine Seite, nicht in ein Handbuch. Eine Teststrategie beantwortet drei Fragen: Welches Risiko wird auf welcher Ebene abgesichert, wo verläuft die Testgrenze, und was bedeutet ein roter Test? Mehr braucht es nicht.
7:35 Der entscheidende Satz steht aber am Ende: Sie gilt erst, wenn die Pipeline sie erzwingt. Ein Dokument im Wiki, das niemand durchsetzt, ist eine Meinung. Sobald aber der Build rot wird, wenn eine Regel verletzt ist, wird aus der Meinung eine Vereinbarung. Deshalb ist eine kurze, erzwungene Strategie mehr wert als ein ausführliches Qualitätskonzept, das nirgends verankert ist.
7:58 Der rote Faden dieser fünf Schritte ist eine Bewegung vom Risiko zur Regel. Sie beginnen nicht bei den Klassen, sondern bei dem, was niemand in Produktion sehen will — falsche Beträge, verlorene Bestellungen, doppelte Belastungen. Für jedes dieser Risiken wählen Sie die Ebene, die es am billigsten abfängt. Dann ziehen Sie die Testgrenze: Was bleibt echt, was wird ersetzt?
8:20 Danach klären Sie, welcher Test wirklich die Pipeline rot färbt. Und der fünfte Schritt, der fast immer fehlt: Schreiben Sie es auf und messen Sie sich beim nächsten Vorfall daran. Ohne ihn bleibt alles Absicht. Das ist die Einsicht, die den Rest des Seminars trägt. Testbarkeit ist keine Eigenschaft der Testsuite, sondern der Anwendung.
8:40 Was ohne Netz, ohne Uhr und ohne Zufall auskommt, prüfen Sie in Millisekunden. Wer die Domäne von der Infrastruktur trennt, braucht für die Fachlogik überhaupt keinen Container. Und umgekehrt: Ein Test, der fünf Attrappen aufbauen muss, meldet Ihnen nicht, dass Testen schwierig ist — er meldet, dass die Klasse zu viele Nachbarn kennt.
9:00 Am zweiten Tag kommen wir genau darauf zurück, wenn wir über Mocking-Überlastung sprechen. Der erste Punkt ist der Klassiker: Die Strategie steht im Wiki, die Pipeline erzwingt etwas anderes — und die Pipeline gewinnt immer. Der zweite betrifft die Testgrenze: Wird sie nie festgelegt, zieht sie jeder Test woanders, und dann ist jede Attrappe irgendwie begründbar.
9:21 Der dritte klingt banal und ist es nicht: Wenn niemand geklärt hat, was ein roter Test bedeutet, wird er zur Verhandlungssache. Und der vierte ist der teuerste: Die Strategie wird einmal geschrieben und nach dem ersten echten Vorfall nicht überprüft. Genau dieser Vorfall wäre die beste Gelegenheit gewesen.
Übung
9:40 Jetzt sind Sie dran. Wir lernen unser Beispielprojekt kennen und bauen die Landkarte, an der wir uns die nächsten drei Tage entlanghangeln. Krautgut ist ein Online-Hofladen: Warenkorb, Staffelpreise, Lieferfenster, und die Zahlung läuft über einen externen Dienst namens Zahlwerk. Eine überschaubare Anwendung mit genau den Problemen, die große auch haben. Ihre Aufgabe ist nicht, Tests zu schreiben — noch keine Zeile Code.
10:05 Ihre Aufgabe ist, die fachlichen Risiken zu benennen und jedem Risiko eine Ebene zuzuordnen. Erfolgreich sind Sie, wenn für jeden Testfall Ebene, Testgrenze und die Frage feststehen, die er beantwortet — und wenn kein Fall zweimal dasselbe prüft. Diese doppelten Fälle sind erstaunlich schwer zu finden. Fangen Sie bei den fünf Fehlern an, die Krautgut Geld oder Vertrauen kosten würden — nicht bei den Klassen. Dann entscheiden Sie je Fehler, auf welcher Ebene er auffallen soll.
10:34 Der dritte Schritt ist der eigentlich schwierige: die Testgrenze ziehen. Was bleibt echt, was wird durch eine Attrappe ersetzt, was wird später zum Container? Und zum Schluss markieren Sie die Fälle, die heute niemand prüft — das sind die interessantesten. Diese Landkarte legen wir am Ende des dritten Tages noch einmal daneben und schauen, was davon eingetreten ist.
10:55 Der erste Fehler passiert in den ersten zwei Minuten: Die Liste beginnt bei den Klassen statt bei den Risiken, und dann steht am Ende eine Struktur, keine Strategie. Der zweite ist der blinde Fleck nach außen — Zahlung und Lieferfenster werden vergessen, weil sie außerhalb der eigenen Anwendung liegen; genau dort passieren aber die teuren Fehler.
11:15 Der dritte ist Reflex: Jeder Fall landet auf der Unit-Ebene, weil das am schnellsten geht. Und der vierte rächt sich später — bleibt die Testgrenze offen, ist am zweiten Tag jede Attrappe begründbar.
Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →