DevOps-Technologie: Kontinuierliche Tests

Der Schlüssel für Qualität im Softwaredesign ist ein schnelles Feedback zu den Auswirkungen von Änderungen während des Lebenszyklus der Softwarebereitstellung. In der Vergangenheit verwendeten Teams manuelle Tests und Codeprüfungen, um die korrekte Funktionsweise von Systemen zu überprüfen. Diese Prüfungen und Tests erfolgten in der Regel in einer separaten Phase nach Abschluss der Entwicklungsphase. Dieser Ansatz hat folgende Nachteile:

  • Manuelle Regressionstests sind zeitaufwendig und kostenintensiv, was sie zu einem Engpass im Prozess macht. Software kann nicht häufig veröffentlicht werden und Entwickler erhalten kein schnelles Feedback.
  • Manuelle Tests und Prüfungen sind nicht zuverlässig, da sich Routineaufgaben wie manuelle Regressionstests nur unzureichend ausführen lassen und es schwierig ist, die Auswirkungen von Änderungen auf ein komplexes Softwaresystem durch Prüfungen vorherzusagen.
  • Wenn die Entwicklung der Software abgeschlossen ist, müssen Entwickler lange warten, bis sie Feedback zu ihren Änderungen erhalten. In der Regel ist anschließend ein erheblicher Aufwand nötig, um Fehler zu untersuchen und zu beheben. Leistungs-, Sicherheits- und Zuverlässigkeitsprobleme erfordern häufig Designänderungen, deren Umsetzung in dieser Phase noch teurer ist.
  • Lange Feedback-Zyklen erschweren es Entwicklern auch, das Erstellen von qualitativ hochwertigem Code zu erlernen, und unter Zeitdruck kann es sein, dass Entwicklungsteams Qualität hin und wieder als "das Problem von jemand anderem" ansehen.
  • Wenn Entwickler nicht für das Testen ihres eigenen Codes verantwortlich sind, können sie schwer lernen, testbaren Code zu schreiben.
  • Bei Systemen, die sich im Laufe der Zeit weiterentwickeln, erfordert das Aktualisieren der Testdokumentation einen erheblichen Aufwand.

Stattdessen sollten Teams:

  • Alle Testarten kontinuierlich während des gesamten Lebenszyklus der Softwarebereitstellung durchführen
  • Schnelle, zuverlässige Suiten von automatisierten Tests erstellen und auswählen, die als Teil Ihrer Continuous-Delivery-Pipelines ausgeführt werden

Dies hilft Teams nicht nur dabei, qualitativ hochwertige Software schneller zu erstellen (und zu lernen, wie man sie erstellt), sondern die Untersuchungen von DORA zeigen auch, dass dies zu einer verbesserten Softwarestabilität, einem geringeren Burnout im Team und geringeren Deployment-Problemen führt.

Kontinuierliche Tests implementieren

Um die Qualität der Software zu verbessern, müssen Sie während des gesamten Bereitstellungsprozesses kontinuierlich sowohl automatisierte als auch manuelle Tests durchführen, um die Funktionalität und Architektur des in der Entwicklung befindlichen Systems zu prüfen. Diese Disziplin umfasst sowohl eine organisatorische als auch eine technische Komponente. Die Untersuchungen von DORA haben ergeben, dass Teams effektiver sind, wenn sie:

  • Testern ermöglichen, während des gesamten Entwicklungs- und Bereitstellungsprozesses der Software mit Entwicklern zusammenzuarbeiten. (Beachten Sie, dass "Tester" eine Rolle ist, nicht unbedingt ein Vollzeitjob, obwohl dies ein gängiges Muster ist, das unten erörtert wird.)
  • Während des gesamten Bereitstellungsprozesses manuelle Testaktivitäten wie explorative Tests, Akzeptanztests und Abnahmetests durchführen.

Eine wichtige technische Aktivität besteht darin, eine Reihe von automatisierten Testsuiten zu erstellen und zu pflegen, darunter:

  • Einheitentests: Hierbei wird normalerweise eine einzelne Methode, Klasse oder Funktion isoliert getestet, um Entwicklern die Gewissheit zu geben, dass ihr Code wie geplant funktioniert. Die Einheitentests müssen erstellt werden, bevor der Code geschrieben wird, um sicherzustellen, dass der Code testbar und die Tests wartbar sind. Dieses Verfahren wird als testgetriebene Entwicklung (Test-Driven Development, TDD) bezeichnet.
  • Akzeptanztests: Hierbei wird normalerweise eine laufende Anwendung oder ein laufender Dienst getestet. In der Regel werden dabei Abhängigkeiten durch Test-Doubles ersetzt. So wird sichergestellt, dass eine höhere Funktionalitätsebene wie geplant funktioniert und keine Regressionsfehler eingeführt wurden. Mit Akzeptanztests können beispielsweise Geschäftsakzeptanzkriterien für eine User Story oder die korrekte Funktionsweise einer API geprüft werden. Schreiben Sie diese Tests im Rahmen des Entwicklungsprozesses. Niemand sollte in der Lage sein, seine Entwicklungsarbeit für abgeschlossen zu erklären, ohne einen automatisierten Akzeptanztest bestanden zu haben.

Das folgende Diagramm wurde ursprünglich von Brian Marick erstellt und später im Buch Agile Testing: A Practical Guide for Testers and Agile Teams referenziert und zeigt die verschiedenen Arten von automatisierten und manuellen Tests.

Bild

Die im vorherigen Diagramm hervorgehobenen automatisierten Tests passen in eine Deployment-Pipeline für Continuous Delivery. In solchen Pipelines führt jede Änderung einen Build aus, der Softwarepakete erstellt und Einheitentests sowie möglicherweise andere Prüfungen durchführt, z. B. statische Analysen. Nachdem diese Pakete die erste Phase durchlaufen haben, werden umfassendere automatisierte Akzeptanztests und möglicherweise auch einige nicht-funktionale Tests wie Leistungstests und Scans auf Sicherheitslücken von automatisch bereitgestellter laufender Software ausgeführt. Jeder Build, der die Akzeptanzphase durchläuft, wird dann in der Regel für manuelle explorative Tests und Tests zur Nutzerfreundlichkeit zur Verfügung gestellt. Wenn in diesen manuellen Schritten keine Fehler gefunden werden, gilt die Anwendung als für die Veröffentlichung geeignet.

Das kontinuierliche Ausführen von Tests als Teil einer Pipeline trägt zu einem schnellen Feedback für Entwickler, einer kurzen Vorlaufzeit vom Check-in bis zur Veröffentlichung und einer geringen Fehlerrate in Produktionsumgebungen bei. Entwickler haben den größten Teil ihrer Arbeit statt in Tagen oder Wochen bereits in wenigen Minuten validiert. Fehler können somit schnellstmöglich behoben werden.

Das folgende Diagramm zeigt ein Beispiel für eine einfache lineare Deployment-Pipeline. In diesem Beispiel bedeutet Grün, dass keine Probleme gefunden wurden. Rot bedeutet, dass ein oder mehrere Probleme festgestellt wurden.

Bild

Im Deployment-Pipeline-Muster wird durch jede Änderung ein Release-Kandidat erstellt und der schnelle Feedback Loop hilft, Probleme so früh wie möglich im Prozess zu erkennen. Wenn ein Paket das Ende der Pipeline erreicht hat, das Team aber immer noch Bedenken bezüglich dessen Veröffentlichung hat, oder wenn Produktionsfehler erkannt werden, muss die Pipeline verbessert werden. Dies kann beispielsweise durch zusätzliche Tests oder eine Aktualisierung vorhandener Tests erreicht werden.

Häufige Schwierigkeiten

  • Keine Entwickler in der Testphase involviert. Untersuchungen von DORA zeigen, dass die Leistung verbessert wird, wenn Entwickler in erster Linie für die Erstellung und Wartung automatisierter Testsuiten verantwortlich sind und es für Entwickler einfach ist, Fehler bei den Akzeptanztests zu beheben. Wenn andere Gruppen für die Testautomatisierung zuständig sind, treten häufig zwei Probleme auf:

    • Testsuiten befinden sich häufig in einem defekten Zustand. Bei Codeänderungen müssen die Tests möglicherweise aktualisiert werden. Wenn Entwickler nicht für die Testautomatisierung verantwortlich sind, bleibt die Build-Pipeline solange unterbrochen, bis das zuständige Team die Tests repariert hat.
    • Entwickler schreiben Code, der schwer zu testen ist. Entwickler neigen dazu, das Problem zu lösen, ohne darüber nachzudenken, wie der Code getestet werden soll. Dies kann zu schlechtem Code und teuren, schwer zu pflegenden Testsuiten führen.

    Tester und QA-Teams spielen weiterhin eine wichtige Rolle bei dieser Arbeitsweise. Tester haben eine einzigartige Perspektive auf das System, weil sie verstehen, wie Nutzer damit interagieren. Es wird empfohlen, Tester mit Entwicklern zusammenarbeiten zu lassen, um die Suiten automatisierter Tests zu entwickeln und weiterzuentwickeln. Dabei werden Tools zur Bildschirmfreigabe verwendet, wenn die Teams sich nicht am selben Standort befinden. Auf diese Weise können sie voneinander lernen und Probleme in Echtzeit lösen. Tester spielen auch eine wichtige Rolle bei der Durchführung von explorativen Tests und Nutzerfreundlichkeitstests sowie bei der Auswahl von Testsuiten.

  • Testsuiten werden nicht bereinigt. Prüfen und verbessern Sie Ihre Testsuiten kontinuierlich, um Fehler besser zu finden und die Komplexität und Kosten unter Kontrolle zu halten. Beispiel:

    • Akzeptanztestsuiten sollten in der Regel eine echte End-to-End-Nutzernavigation durch das System vorführen, statt nur Sammlungen automatisierter Akzeptanzkriterien zu sein. Mit der Weiterentwicklung Ihres Produkts werden sich auch diese Szenarien und die Testsuiten, durch die sie validiert werden, entsprechend weiterentwickeln. Weitere Informationen zu diesem Prozess finden Sie im Video Setting a Foundation For Successful Test Automation von Angie Gibson.
    • Wenn Sie bei jeder Codeänderung auch mehrere Einheitentests ändern müssen, verlassen Sie sich entweder zu sehr auf Simulationen oder versäumen es, Ihre Einheitentestsuite zu bereinigen.
    • Sie sollten Ihre Testsuiten regelmäßig optimieren. Wenn bei jeder Änderung der Benutzeroberfläche mehrere Akzeptanztests fehlschlagen, entkoppeln Sie Ihre Tests mithilfe des Seitenobjektmusters vom zu testenden System.
    • Wenn Ihre Tests teuer sind, kann dies auf Probleme mit der Architektur Ihrer Software hinweisen. Achten Sie darauf, dass Sie fortlaufend in die Software investieren, sodass sie sich leicht testen lässt, einschließlich der Einbindung von Refaktorierung in die tägliche Arbeit Ihres Teams.
  • Ein falsches Verhältnis von Einheiten- und Akzeptanztests. Eines der Entwicklungsziele für automatisierte Testsuiten besteht darin, Fehler so früh wie möglich zu erkennen. Aus diesem Grund werden Einheitentests, die eine kürzere Ausführungszeit haben, zeitlich vor Akzeptanztests ausgeführt, die eine längere Ausführungszeit haben. Erst nach Ausführung dieser beiden Tests werden manuelle Tests vorgenommen.

    Fehler sollten mit der schnellsten Testkategorie gefunden werden. Wenn Sie einen Fehler in einem Akzeptanztest oder während eines explorativen Tests finden, fügen Sie einen Einheitentest hinzu. Damit sorgen Sie dafür, dass dieser Fehler beim nächsten Mal schneller, früher und kostengünstiger erkannt wird. Mike Cohn hat die ideale Testautomatisierungspyramide beschrieben, die in der folgenden Abbildung dargestellt ist und bei der die meisten Fehler mithilfe von Einheitentests erkannt werden.

    Bild

  • Unzuverlässige Tests tolerieren. Tests sollten zuverlässig sein: Das heißt, wenn die Tests bestanden werden, sollten wir sicher sein können, dass die Software zur Veröffentlichung bereit ist. Fehler beim Testen sollten auf ein echtes Problem hindeuten. Akzeptieren Sie insbesondere keine unklaren Tests. Hier finden Sie Informationen zur Google-Strategie zur Vermeidung unklarer Tests.

Möglichkeiten zur Verbesserung kontinuierlicher Tests

Machen Sie sich keine Sorgen, wenn Ihre Organisation noch nicht standardmäßig Einheitentests von Entwicklern durchführen lässt. Einheitentests waren in den Anfangsjahren bei Google keine allgemein übliche Praxis. Der aktuelle gängige Ansatz umfassender Einheitentests wurde von einer Gruppe von Freiwilligen bei Google namens "Testing Grouplet" vorangetrieben. Hier erfahren Sie, wie sie zur Einführung von Einheitentests beitrugen, indem sie eine sogenannte Community of Practice aufbauten, die sich auf die Verbreitung von Testwissen bei Google konzentrierte und Entwickler vom Nutzen von Einheitentests überzeugte.

Wenn Sie nicht über genügend Testautomatisierung verfügen, erstellen Sie zuerst eine Deployment-Pipeline. Erstellen Sie beispielsweise einen einzigen Einheitentest, einen einzigen Akzeptanztest und ein automatisiertes Deployment-Skript, das eine explorative Testumgebung bereitstellt. Verknüpfen Sie die einzelnen Elemente dann miteinander. Erhöhen Sie anschließend schrittweise die Testabdeckung und erweitern Sie Ihre Deployment-Pipeline, wenn sich Ihr Produkt oder Ihre Dienstleistung weiterentwickelt.

Wenn Sie bereits an einem Brownfield-System arbeiten, befolgen Sie die Anleitungen in diesem Artikel, ohne jedoch die Nachrüstung einer umfassenden Suite automatisierter Tests zu unterbrechen. Schreiben Sie stattdessen eine kleine Anzahl von Akzeptanztests für wichtige Funktionen. Sorgen Sie dann dafür, dass Entwickler Einheiten- und Akzeptanztests für neue und geänderte Funktionen schreiben. Erwägen Sie die Verwendung von TDD, um die Qualität und Wartung von Haupt- und Testcode zu verbessern. Wenn die Akzeptanztests fehlschlagen, schreiben Sie Einheitentests, um den Fehler in Zukunft schneller zu erkennen.

Wenn Sie eine Testsuite haben, deren Wartung teuer und unzuverlässig ist, bereinigen Sie sie. Eine Testsuite mit zehn Tests, die zuverlässig, schnell und vertrauenswürdig ist, ist viel besser als eine Testsuite mit Hunderten von Tests, die schwer zu warten ist und der niemand vertraut.

Möglichkeiten zum Messen bei kontinuierlichen Tests

So können Sie die Ergebnisse kontinuierlicher Tests in Ihrer Umgebung messen:

Faktor zum Testen Geeignete Messwerte Ziel
Autoren von Akzeptanz- und Einheitentests. Prozentsatz der Tests, die von Entwicklern, Testern und anderen Gruppen in Ihrem Unternehmen geschrieben wurden. Die Hauptautoren und Betreiber von Akzeptanztests sind Entwickler.
Anzahl der Fehler, die bei Akzeptanztests, explorativen Tests und in der Produktion gefunden wurden. Änderung des Anteils der gefundenen Fehler im Zeitverlauf. Mehr Fehler werden in "billigeren" Testphasen gefunden. Teams fügen automatisierte Tests für die Fehler hinzu, die Sie während explorativer Tests und der Produktion finden, und fügen Einheitentests hinzu, um Fehler zu erkennen, die bei Akzeptanztests gefunden wurden.
Zeitaufwand für die Behebung von Fehlern in Akzeptanztests. Zeitliche Änderung bei der Behebung von Testfehlern im Zeitverlauf. (Sollte sich verringern.) Entwickler können Fehler bei Akzeptanztests problemlos beheben.
Automatisierte Tests sind aussagekräftig. Verfolgung der Anzahl automatisierter Testfehler, die echte Fehler sind, und die Anzahl der Fehler, die auf eine schlechte Codierung zurückzuführen sind. Testfehler deuten immer auf einen echten Produktfehler hin.
Automatisierte Tests werden in der Bereitstellungs-Pipeline ausgeführt. Überprüfung (Ja/Nein), ob alle Testsuiten in jedem Pipeline-Trigger ausgeführt werden. Automatisierte Tests werden im Rahmen der Haupt-Pipeline und des Workflows ausgeführt.

Weitere Informationen