Turbo für Digitalisierungsprojekte

Software-Entwicklung durch automatisierte Tests beschleunigen

26.01.2017
Von Christoph  Deppisch und Tobias Schneck
Um Digitalisierungsprojekte voranzutreiben müssen Anwendungen immer schneller bereitgestellt werden. Deshalb muss ein IT-Verantwortlicher langwierige und komplexe Software-Tests vermeiden und durch automatisierte Prozesse ersetzen. Im Ergebnis heißt das Zauberwort "Continuous Delivery".

IT-Verantwortliche stehen durch den steigenden Digitalisierungszwang in Unternehmen enorm unter Druck. Um konkurrenzfähig zu bleiben, müssen sie Software schneller und zuverlässiger in die Produktionsabläufe integrieren, als die Konkurrenz. Nur mit einem hohen Automatisierungsgrad lassen sich solche Aufgaben heute noch bewältigen. Eine Strategie auf Basis von Continuous Delivery kann aus diesem Dilemma helfen. Denn für die schnelle und kontinuierliche Bereitstellung von Anwendungen sind vollständig automatisierte Unit-, Integrations- und UI-Tests unerlässlich. Sie sind notwendig, um den Weg zur Einführung eines reibungslosen Continuous-Delivery-Prozesses zu ebenen.

Ohne dedizierte Tests ist eine erfolgreiche Softwarelieferung kaum denkbar. So wird während des gesamten Entwicklungsprozesses die Anwendung auf drei Ebenen getestet.

Auf der ersten Ebene gibt es die sogenannten Unit-Tests, bei denen eine bestimmte Klasse oder Methode einzeln und isoliert von anderen Einheiten geprüft wird. Sie werden üblicherweise von Entwicklern erstellt und stellen sicher, dass ein bestimmter Code-Abschnitt sich wie erwartet verhält.

Die Konzentration auf einzelne Einheiten bedeutet aber, dass die korrekte Zusammenarbeit mehrerer Komponenten im Unit-Test nicht überprüft wird. Hierfür ist die nächste Ebene zuständig: der Integrationstest, in dem das Zusammenspiel mehrerer Bausteine im Mittelpunkt steht. Dabei werden immer mehrere Code-Module und deren Schnittstellen überprüft.

Die dritte Ebene sind sogenannte User-Interface (UI)-Tests, in denen die Benutzeroberfläche einer ganzen Anwendung mit simulierten Anwendereingaben geprüft wird. Durch die Validierung des Erscheinungsbilds und der Funktionalität wird sichergestellt, dass die vom Server gelieferten Daten auch richtig angezeigt werden, was insbesondere bei der Fehlerbehandlung eine wichtige Rolle spielt.

Testautomatisierung verbessert Softwarequalität

Die Automatisierung dieser drei Testarten bekommt eine immer größere Bedeutung. Entwicklungsbegleitende, voll automatisierte Tests stellen kontinuierlich die Release-Fähigkeit der Software fest. Damit kann die Stabilität einer Anwendung viel öfter und vor allem früher im Entwicklungsprozess beurteilt werden, so dass potenzielle Fehler schneller und häufiger erkannt werden.

Allerdings sind die verschiedenen Testarten nicht gleich einfach zu automatisieren. Bei Unit-Tests ist die Automatisierung durch Frameworks wie JUnit etabliert und gilt als Standard in der Softwareentwicklung. Abhängigkeiten werden durch Mocks ersetzt. Dadurch lassen sich die Unit-Tests schnell und einfach ausführen.

Integrations- und UI-Tests dagegen benötigen eine komplexere Infrastruktur. Die Anwendung muss komplett gestartet werden und Abhängigkeiten zu anderen Systemen und Komponenten müssen simuliert werden, um aussagekräftige Ergebnisse zu liefern. Die Vorbereitung der richtigen Infrastruktur hat eine deutlich höhere Komplexität und bedeutet Aufwand. Bei der Überprüfung der Oberfläche kommt zusätzlich noch die Simulation von validen Anwendereingaben hinzu.

Viele Manager scheuen deshalb häufig die Kosten für das Einführen einer vollständigen Testautomatisierung in den Bereichen Integrations- und UI-Tests. Mit den richtigen Tools bleibt aber auch diese Investition im Rahmen, so dass sich kontinuierliche, vollautomatische Tests mittel- und langfristig immer lohnen. Die Releasefähigkeit einer Anwendung kann durch Testautomatisierung kostengünstig und schnell überprüft werden und ist Voraussetzung für eine zeitgemäße Time-to-Market-Strategie. Manuelle Tests sind dann nur noch ausgewählten Fachanwendern vorbehalten, die sich vor einem Release ganz gezielt auf die neuen Funktionen einer Anwendung konzentrieren, um die Übereinstimmung mit den Anforderungen zu prüfen und fachliche Fehler auszuschließen.

Testautomatisierung vereinfacht die Fehlersuche

Unternehmen sollten in Entwicklungsprojekten bereits von Anfang an eine Automatisierung vorsehen. Dabei müssen alle drei Testarten fester Bestandteil des Build-Prozesses sein, damit sie bei jeder Änderung automatisch ausgeführt werden. Bei der Einbindung in die Build-Umgebung gilt das Prinzip des Failfast-Ansatzes, bei dem ein Fehlschlag dazu führt, dass die weiteren Prozess-Schritte nicht mehr ausgeführt werden.

Die Anzahl der Tests und die Vielfalt der Varianten, die getestet werden, nehmen mit jeder Testebene von unten nach oben immer weiter ab. Basis dieser Hierarchie sind die schnell ausführbaren Unit-Tests, die sehr nah am Quellcode arbeiten und dabei viele Varianten sowie möglichst alle Entscheidungswege prüfen. Danach verschiebt sich der Fokus auf ausgewählte Tests von Komponenten und Schnittstellen. Auf der letzten Ebene wird gezielt die Anwendererfahrung ausgewertet und das Gesamtsystem kommt in den Blick.

Die sinkende Anzahl der Testvariationen in den oberen Testhierarchieebenen sorgt für eine größere Effizienz des gesamten Entwicklungsprozesses. Wegen des größeren Aufwands und der deutlich längeren Ausführungszeit der Tests im Bereich Integration und UI wird der Durchlauf auf die wesentlichen Prüfroutinen beschränkt.

Eine wichtige Randbedingung erfolgreicher Testautomatisierung ist die Organisation der Projektteams. Die Erfahrung zeigt, dass cross-funktionale Teams, die alle Bereiche wie Test, Softwareentwicklung und Releasemanagement behandeln, die beste Lösung sind. Bessere Kommunikation und Zusammenarbeit sowie eine gleichmäßigere Wissensverteilung unter den Mitarbeitern sind die Folge.

Kurze Wege und regelmäßiger Austausch vermeiden zeitintensive Kommunikationsschleifen zwischen Bug-Eröffnung, Test-Verifizierung und Bug-Behebung. Daher ist es beim Beginn des Projekts empfehlenswert, eine gemeinsame Arbeitsgrundlage mit einem einheitlichen Vorgehensmodell wie Scrum oder Kanban sowohl für die Entwicklung als auch das Testen zu finden.

Sichtbarkeit der Tests im Team

Eine besonders kritische Situation im Entwicklungsprozess entsteht, wenn über Stunden oder Tage im "Continuous Build" mehrere Fehler auflaufen und sich überlagern. Dadurch kann niemand nachvollziehen, welcher Fehler zu welcher Code-Änderung gehört. Dies erschwert die Fehlerbehebung unnötig und muss unbedingt verhindert werden.

Wenn das Entwicklerteam nicht auf Stabilität achtet, gewöhnen sich rasch alle an einen fehlerhaften Build und es sinkt zunehmend die Bereitschaft, die Fehler zu beseitigen. Nach kurzer Zeit ist dann keine korrekte Aussage über die Qualität der Software mehr möglich. Dieser Zustand verhindert das Deployment oder führt zu unerkannten Fehlern im Produktivsystem.

Eine gute Lösung ist es, in der täglichen Teambesprechung Fehler im Continuous Build in Listenform zusammenzutragen und anschließend in eine Rangfolge zu bringen. Dies erhöht für das Team die Sichtbarkeit der Tests und der Zuständigkeiten für einen fehlgeschlagenen Build. Um die Qualität dauerhaft hoch zu halten, sollte die Feedback-Schleife des Builds kurzfristig alle notwendigen Daten zur Fehleranalyse liefern. Der Test-Code sollte Gegenstand eines Reviews sein, um die Einhaltung von Guidelines dauerhaft sicherzustellen.

Ein empfehlenswertes und den Gesamtablauf entlastendes Verfahren ist eine Vereinbarung im Team, vor dem Check-in des Quellcodes Unit- und ausgewählte Integrations-Tests lokal auszuführen, um offensichtliche Fehler schon vorab zu bemerken.

Continuous Deployment als nächste Stufe der Automatisierung

Die Testautomatisierung ist nur der erste Schritt einer Continuous-Delivery-Pipeline. Nach den Tests folgt das automatisierte Deployment der Anwendung zum Beispiel in Form eines Java-Web-Archivs in einem Application Server. Das Artefakt wird automatisiert durch den Build erstellt, getestet und in ein Repository zum Beispiel Maven oder Docker abgelegt.

In diesem Zusammenhang bedeutet Automatisierung, dass nach dem Commit des Entwicklers keine manuellen Aktionen notwendig sind, um das fertige Artefakt zu erhalten. Tools wie Jenkins besitzen alle notwendigen Funktionen, um eine solche Continuous Integration (CI) Pipeline aufzusetzen. Der nächste Schritt ist dann Continuous Delivery. Hier wird die CI-Pipeline um ein automatisiertes Deployment erweitert, das ein beliebiges Zielsystem mit einem Klick aktualisiert.

In diesem Kontext können verschiedene manuelle Genehmigungsschritte eingebaut sein. Denkbar ist, dass ein Testmanager Systeme für die Abnahme mit einem einzigen Klick bereitstellen kann. Für das Deployment der Produktivumgebung hingegen könnte nur ein bestimmtes Betriebsteam die Berechtigung haben. Sobald diese automatischen Prozesse fehlerfrei ablaufen und einen hohen Reifegrad erreicht haben, kann als nächster Schritt zur vollständigen Automatisierung das Continuous Deployment eingeführt werden. Der Auslöser für die Bereitstellung der Produktivumgebung ist hier entweder der Commit eines Entwicklers oder ein Zeitintervall - zum Beispiel nachts um 3 Uhr.

Nicht jeder Automatisierungsgrad ist für alle Projekte sinnvoll, organisatorische Rahmenbedingungen müssen bei der Entscheidung berücksichtigt werden. Unternehmen sollten aber auf jeden Fall ein automatisiertes Deployment anstreben. Damit kann sich das Projektteam auf die Kernaufgabe der Anwendungsentwicklung konzentrieren. Die manuelle Bereitstellung von Test- und Produktivsystemen lenkt von der Hauptsache ab, ist im Nachhinein schwer nachvollziehbar und nicht wiederholbar, meist schlecht dokumentiert und somit nicht effizient genug.

Fazit

Die vollständige Automatisierung der Unit-, Integrations- und UI-Tests ist eine Grundvoraussetzung für Continuous Delivery in der Softwareentwicklung. Die Überprüfung der Anwendungsintegration und Benutzerschnittstellen sind schwieriger zu automatisieren und benötigen spezielle Vorbereitungen bezüglich Infrastruktur und Testdaten. Durch den Einsatz spezialisierter Tools lässt sich dieser Aufwand beherrschen und die Automatisierung wird eine mächtige Waffe im Kampf gegen Bugs.

Automatisierte Tests ermöglichen schnelle und häufige Lieferungen einer Software und sind bei einem zukünftigen Refactoring wertvoll. Der erhöhte Testaufwand zahlt sich damit bei jeder Lieferung und jedem frühzeitig entdeckten Fehler doppelt aus. Schnelle Feedback-Zyklen und definierte organisatorische Zuständigkeiten sind nicht zuletzt auf dem Weg zu einem erfolgreichen Continuous-Deployment-Prozess unverzichtbar.