Testautomatisierung in Zeiten von Continuous Delivery

Durch Continuous Delivery haben sich die Herausforderungen beim automatisierten Softwaretesten in den Bereichen Unit-, Integrations- sowie UI-Tests verändert. Doch selbst spezialisierte Tester sehen sich hier mit großen Schwierigkeiten konfrontiert. Glücklicherweise gibt es zeitgemäße Lösungsansätze für einen reibungslosen Prozess.

In Pocket speichern vorlesen Druckansicht 1 Kommentar lesen
Testautomatisierung in Zeiten von Continuous Delivery
Lesezeit: 20 Min.
Von
  • Christoph Deppisch
  • Tobias Schneck
Inhaltsverzeichnis

Software ist auf mehreren Ebenen zu testen. Es gibt als kleinste Einheit Unit-Tests. Meistens von Entwicklern selbst erstellt, überprüfen sie eine abgeschlossene Funktionalität (zum Beispiel eine Klasse oder eine Methode) in voller Isolation. Abhängigkeiten zu anderen Einheiten und Einflüsse von außen werden durch Mocks ersetzt. Damit stellen Entwickler sicher, dass sich ein Code-Abschnitt wie erwartet verhält. Unit-Tests bilden die Basis der Testabdeckung und gelten in der Softwareentwicklung als Standard.

Die Isolation im Unit-Test hat allerdings Konsequenzen. Die korrekte Zusammenarbeit mehrerer Komponenten ist kein Bestandteil des Tests. Zuständig hierfür sind hier als nächste Ebene in der Testhierarchie Integrationstests. Bei ihnen steht das Zusammenspiel mehrerer Bausteine im Mittelpunkt. Nachrichtenbasierte Schnittstellen nach außen oder auch die Deployment-Konfiguration für einen Application Server werden etwa zum Gegenstand. Beispiele hierfür sind Connection Pools und Factories, JNDI-Ressourcen oder Fremdabhängikeiten, die via Dependency Injection zum Deployment-Zeitpunkt konfiguriert werden.

Es sind immer gleich mehrere Komponenten an einem Integrationstest beteiligt. Die Automatisierung der Integration ist deshalb weitaus schwieriger als bei Unit-Tests. Um aussagekräftige Tests zu ermöglichen, sind die Abhängigkeiten zu anderen Systemen zu simulieren. Die benötigten Komponenten mit ihrer Infrastruktur und Konfiguration müssen aufgesetzt werden. Beides hat eine deutlich höhere Komplexität und bedeutet Aufwand.

Nachdem das Zusammenspiel einzelner Komponenten und deren Integration getestet wurde, fehlen UI-Tests für die Überprüfung der Benutzeroberfläche (zum Beispiel ein Web-Frontend oder eine Rich-Client-Anwendung). Sie simulieren Benutzerinteraktionen und bedienen so das User Interface. Während der Simulation werden das Erscheinungsbild und die Funktionen der UI validiert. Der Test soll sicherstellen, dass die vom Server gelieferten Daten richtig angezeigt werden, was insbesondere bei der Fehlerbehandlung eine wichtige Rolle spielt.

Die drei Testarten zählen zu den wichtigsten in der Softwareentwicklung. Die Automatisierung in allen Bereichen nimmt in der heutigen Softwareentwicklung eine zunehmend wichtigere Stellung ein. Das ist der Tatsache geschuldet, dass die Applikationsentwicklung Bugfixes und neue Features häufiger und schneller in Produktion bringen muss. Teams werden in immer kürzeren Abständen mit der Aufgabe betraut, eine Softwareversion auf Releasefähigkeit zu überprüfen. Daher müssen alle Tests wiederholbar und effizient ausführbar sein.

Eine umfangreiche Testphase vor jedem Release mit womöglich noch einer Menge manueller Tests kann sich kein Team mehr leisten. Um am Markt bestehen zu können, stellen entwicklungsbegleitende, vollautomatisierte Tests die Releasefähigkeit eines Softwarestandes kontinuierlich fest. Damit lässt sich die Stabilität einer Software öfter und vor allem früher im Entwicklungsprozess beurteilen. Eine Aktualisierung der Software ist somit schneller und häufiger möglich.

Das Konstrukt der vollautomatisierten Tests setzt allerdings ein Umdenken des Managements voraus. Viele Projektleiter und Auftraggeber sehen die Notwendigkeit der Testautomatisierung traditionell im Bereich der Unit-Tests. In den Bereichen Integrations- und UI-Tests ist die Bereitschaft, entsprechende Mittel bereitzustellen, meist nicht vorhanden. Das liegt unter anderem daran, dass der initiale Aufwand für eine vollständige Testautomatisierung im Vergleich zu manuellen Tests hoch ist. Alle Beteiligten müssen sich bewusst sein, dass Testautomatisierung keine Nebensache ist.

Wer den Aufwand für manuelles Testen gegenüberstellt, dem wird schnell klar, dass sie nur auf kurze Sicht kostengünstiger sind. Mittel- und langfristig lohnen sich automatisierte Tests in allen Bereichen – sowohl finanziell als auch qualitativ. Manuelle Tests sind idealerweise nur noch den Fachexperten vorbehalten, die sich ganz gezielt vor einem Release auf die neuen Funktionen einer Anwendung konzentrieren, bevor das neue Stück Software seinen Weg in die Produktion findet.

Es empfiehlt sich, von Beginn an eine entwicklungsbegleitende Automatisierung anzustreben. Genau wie bei Unit-Tests sollten die Integrations- und UI-Tests fester Bestandteil des Build-Prozesses sein, damit bei jeder Änderung auch alle Tests automatisch ausgeführt werden. Beim Einbinden in die Build-Umgebung gilt das Prinzip des Fail-fast-Ansatzes. Unit-Tests werden als Erstes angegangen, und schlägt ein Test fehl, werden alle folgenden in der Hierarchie nicht mehr ausgeführt.

Testpyramide (Abb. 1)

Wie in Abbildung 1 dargestellt, nimmt die Anzahl der Tests und die Vielfalt der getesteten Varianten von unten nach oben zunehmend ab, sodass sich das Bild einer Pyramide ergibt. Die geringer werdende Anzahl der Tests nach oben in der Pyramide ist sinnvoll. Zum einen sind Integrations- und UI-Tests deutlich aufwendiger in der Pflege und im Set-up. Zum anderen ist die Ausführzeit der Integrations- oder UI-Tests höher als bei den Unit-Tests.

Es wird also eine effizientere Laufzeit des gesamten Testdurchlaufs erreicht, wenn man die Tests nach oben hin immer weiter aufs Wesentliche beschränkt. Nur wenn das Feedback eines Testdurchlaufs zeitnah geschieht, ist die Wahrscheinlichkeit hoch, dass Entwickler das Ergebnis des Tests noch ohne großen Aufwand einer dedizierten Code-Änderung zuordnen können. Die Gefahr einer mühsamen und zeitintensiven Fehlersuche lässt sich dadurch deutlich reduzieren.

Die erfolgreiche Testautomatisierung steht und fällt oft mit der Organisation des Projekts. Entweder wird ein festes Testteam bestimmt, das sich ausschließlich um die Pflege der Testfälle kümmert, oder ein übergreifendes Team ist gleichermaßen für Entwicklung und Tests zuständig.

Crossfunktionale Teams haben viele Vorteile. Bessere Kommunikation und Zusammenarbeit sowie eine gleichmäßigere Wissensverteilung im Team sind nur zwei der wesentlichen Punkte. Ein solches Team vermeidet zeitintensive Kommunikationsschleifen zwischen Bug-Eröffnung, Testverifizierung und Bug-Behebung. Daher empfiehlt sich beim Projekt-Set-up, ein gemeinsames Vorgehensmodell (Scrum, Kanban) sowohl für die Entwicklung als auch das Testen zu finden.