Softwaretest und wofür sie eigentlich wichtig sind

Wir schreiben das Jahr 2022 und Sie haben sich nun auch entschlossen, Ihr Unternehmen zu digitalisieren und einige Prozesse zu automatisieren oder sogar die Türen für Online-Nutzer:innen zu öffnen. Eine gute Idee! Doch dann erhalten Sie den Kostenvoranschlag Ihrer Softwareentwicklungsagentur  und fragen sich: Warum zum Teufel verschlingt die “Qualitätssicherung” zwei Drittel des Budgets? Nun, sehen wir uns an, wie das funktioniert, warum das so wichtig ist wofür Sie genau bezahlen.

Wahrscheinlich haben Sie in der Vergangenheit schon einige Artikel gelesen und Videos gesehen, in denen beschrieben wurde, wie Satelliten aus der Umlaufbahn stürzten oder der Dritte Weltkrieg kurz vor dem Ausbruch stand, weil ein Programmierfehler in einer entsprechenden Software vorlag. Da Software von Menschen entwickelt wurde und wird, kann es natürlich zu allen möglichen Pannen kommen, die sich unterschiedlich stark auswirken. Die Minimierung dieser Auswirkungen ist einer der Gründe für die Existenz der Qualitätssicherung oder, einfacher ausgedrückt, des Softwaretests. Das weiß normalerweise jede:r Unternehmer:in, der sich mit der Automatisierung/Digitalisierung seines Unternehmens beschäftigt.

Die Problematik ist die, dass es viele verschiedene Ebenen und Ansätze für das Testen gibt. Bevor wir mit der Diskussion darüber beginnen, sollten Sie eines wissen: Kaum ein:e Softwareentwickler:in testet gerne ins leere hinein – deshalb muss der/die Kund:in proaktiv sein und sich in den gesamten Prozess einbringen.

Ablauf Softwareentwicklung

Die Softwareentwicklung beginnt in der Regel damit, dass man ein Konzept erstellt und die Anforderungen festlegt, die eine neue Software oder Webanwendung erbringen soll. Unabhängig davon, ob der Entwicklungsablauf “agil” ist oder im klassischen Wasserfallmodell umgesetzt wird, sollten vor Beginn der eigentlichen Arbeit die Anforderungen an das Produkt festgelegt werden. Um mit der finalen Entwicklung zu starten brauchen wir im Grunde eine erklärte Definition eines funktionierenden Produkts. Stellen Sie sich vor, Sie gehen zu eine:m Automobilverkäufer:in und sagen, dass sie gerne ein Fahrzeug kaufen wollen – dabei sind die Möglichkeiten enorm: Kraftrad, Auto, Sprinter, LKW’s und alle mit der unterschiedlichsten Ausstattung – vom Roller bis hin zum Elektroauto von Tesla. Im nächsten Gespräch werden Sie dann ihre Wünsche und Anforderungen an das Fahrzeug darlegen, damit sie das passende Modell erwerben können. Und genauso geht es uns auch, Software und Webanwendungen kann man in die unterschiedlichsten Richtungen denken und programmieren.

Und was hat das jetzt mit Softwaretests zu tun?

Nun, Qualitätssicherung ist der Prozess, der sicherstellt, dass die Software die Kundenanforderungen erfüllt. Grundsätzlich sollte man als Auftraggeber:in, am Ende in der Lage sein, Anforderungen auf verschiedenen Ebenen zu definieren. Stellen Sie sich zum Beispiel vor, die Webanwendung soll Preise für Ihre Dienstleistung auf der Grundlage mehrerer Bedingungen berechnen. Dann sind Sie dafür verantwortlich, alle möglichen Faktoren und Formeln aufzuschreiben, damit die Webanwendung ihren Job richtig macht.

Verschiedene Ebenen der Qualitätssicherung und Tests der Softwareentwicklung

Alphatest

Wie bereits erwähnt, gibt es mehrere Ebenen der Qualitätssicherung. Sobald die Software fertig ist oder ein Teil dieser, wird in der Regel eine stabile Version davon bereitgestellt und ein so genannter “Alphatest” eingeleitet. Hierbei klicken sich Entwickler:innen und/oder Kundenvertreter:innen durch die Software, fügen einige Dummy-Daten hinzu und notieren etwaige Probleme oder Abstürze. Dies wird so lange wiederholt, bis die Funktion/die Software als stabil genug erachtet wird, um sie/es echten Endnutzer:innen zu zeigen.

Betatest

Dieser Ansatz für das Testen von Software ist Teil eines Prozesses, der als funktionales Testen bezeichnet wird. Eine ganze Anwendung oder ihre Komponenten werden als “Black Boxes” behandelt, wenn das Benutzerverhalten, die Eingabedaten, die Sensoranzeigen usw. das Ergebnis liefern sollen, das im Voraus definiert wurde. Diese Definitionen basieren auf dem Geschäftsprozess, der optimiert werden soll: Normalerweise werden die Funktionstests von Teammitgliedern durchgeführt, die nicht direkt am “Schreiben des Codes” beteiligt sind (obwohl einige Teile der Funktionstests automatisiert werden können) – Kundenvertreter, spezielle QA-Teams, usw. Um effizient zu sein, sollte es eine klare Definition von Testfällen geben, und zwar sowohl für abstrakte Szenarien (z. B. ein Formular sollte einen Validierungsfehler anzeigen, wenn Feld A oder B leer bleibt) als auch für den Geschäftsablauf im Allgemeinen (z. B. das Speichern eines Formulars sollte dazu führen, dass ein Benutzer angelegt wird und dieser Benutzer per E-Mail benachrichtigt wird).

Das ist das Mindestmaß an Softwaretests, die es überall gibt. Und, um ehrlich zu sein, reicht es für 60 % der Projekte aus, allerdings erfordern solche Anwendungen auch einen höheren Wartungsaufwand.

Die Testszenarien sollten theoretisch den gesamten Prozess der Benutzerinteraktion mit der Anwendung abdecken: Wichtigstes Kriterium ist hier die Reproduzierbarkeit. Grundsätzlich sollten die gleichen Eingaben zu den gleichen Ausgaben führen. Es sollte sowohl positives als auch negatives Verhalten getestet werden. Wie bereits erwähnt, gibt es für die meisten Anwendungen (vor allem für kleinere) keine formell geschriebenen Anwendungsfälle oder Testszenarien, aber am Ende gibt es jemanden in der ganzen Konstellation, der alles in seinem Kopf hat. Daher sollten Sie als Kunde daran interessiert sein, die Akzeptanzkriterien mit dem Entwicklungsteam zu teilen, um wilde Vermutungen und potenziell verschwendete Zeit zu vermeiden.

Automatisierte Tests

Natürlich gibt es Tools, die funktionale Tests auf verschiedenen Ebenen automatisieren: Normalerweise simulieren sie eine Benutzerinteraktion mit verschiedenen Schnittstellen der Software und prüfen, ob das Ergebnis den Erwartungen entspricht. Wenn ein Produkt jedoch nicht ständig verbessert werden muss, sind gute Alpha- oder Beta-Tests (letzteres bedeutet, dass die Anwendung, die kurz vor dem Release steht, von echten Endbenutzern getestet wird) oft ausreichend. Dies erfordert jedoch, dass das Entwicklungsteam ein wenig mehr Zeit für die aktive Überwachung der laufenden Software aufwendet, insbesondere nach jeder Veröffentlichung. Wir (und die meisten Entwickler) haben Benachrichtigungen für den Fall eingerichtet, dass die Software etwas Unerwartetes tut (z. B. abstürzt oder einen Datenbankfehler verursacht), so dass die meisten Probleme recht schnell eingegrenzt und behoben werden können.

Unit-Tests

Natürlich sind Funktionstests, ob manuell oder automatisiert, wichtig. Es gibt jedoch eine Qualitätssicherung der Codequalität und -stabilität, die außerhalb des Entwicklerteams, das für die eigentliche Implementierung zuständig ist (das “Schreiben des Codes”), nicht erreicht werden kann. Hier kommen die Unit-Tests ins Spiel, bei denen sichergestellt wird, dass einzelne Codeblöcke oder sogar ganze Module wie erwartet funktionieren. Die Idee dabei ist, dass jede nicht-triviale Funktion oder Prozedur einen programmgesteuerten Test haben sollte, der genau dieses Ziel erreicht. Da der Code während des Entwicklungsprozesses geändert wird, ist es wichtig zu wissen, dass Aktualisierungen und Verbesserungen keine Funktionalität zerstören (bekannt als Regression – Fehler in zuvor funktionierenden Codeblöcken).

Unit-Tests werden oft auf ein Minimum reduziert, um Kosten zu sparen. Wie bereits erwähnt, schreibt kaum ein:e Entwickler:in gerne Testfälle, aber es ist eine Voraussetzung für ein besseres Endprodukt. Für jede kommerziell genutzte moderne Programmiersprache gibt es eine Vielzahl von Unit-Test-Frameworks, die eine schnellere Implementierung von programmatischen Unit-Tests ermöglichen. Um diese Tests so effizient wie möglich zu gestalten, ist es wichtig, dass ein:e Kund:in in der Lage ist, die Geschäftslogik im Hinblick auf die möglichen Eingaben und Ergebnisse von Normal- und Grenzfällen klar zu definieren.

Eine der Metriken, die zur Bestimmung der Code-“Qualität” verwendet werden, ist die so genannte “Codeabdeckung”. Der Grundgedanke dabei ist, dass in einem funktionierenden Softwaremodul alle Zeilen/Blöcke des Codes durch Tests “abgedeckt” sein sollten – ausgeführt, während diese Tests laufen. Die Codeabdeckung wird mit Hilfe eines externen spezialisierten Tools bewertet, das von der verwendeten Programmiersprache/dem verwendeten Framework abhängt. Normalerweise ist es unmöglich, eine 100%ige Codeabdeckung zu erreichen, und da es Szenarien gibt, die sich nicht automatisch testen lassen, sollte sie nicht als KPI verwendet werden. Eine signifikante Änderung der Codeabdeckung zwischen den einzelnen Testläufen ist jedoch ein Zeichen dafür, dass etwas nicht in Ordnung ist.

Es gibt sogar Softwareentwicklungsparadigmen, die Unit-Tests aktiv als Teil der Produktentwicklung selbst einsetzen. Bei der so genannten “testgesteuerten Entwicklung” müssen die Unit-Tests im Grunde vor dem eigentlichen Code geschrieben werden und dienen als weitere Ebene der Aufgabendefinition. Allerdings verwenden nur wenige Teams dieses Konzept in reiner Form und bevorzugen den praktischeren Ansatz, die Testfälle zu aktualisieren, wenn der neue Code hinzugefügt wird.

Eine Ebene über den Unit-Tests steht das Konzept der Integrationstests. Wenn ein Softwareprodukt aus mehreren Modulen besteht, an denen möglicherweise mehrere Entwicklungsteams beteiligt sind (oder, was häufiger der Fall ist, externe Softwarebibliotheken und/oder -dienste verwendet werden), muss jedes Mal, wenn sich etwas in dieser Konstellation ändert, überprüft werden, ob sie zusammenarbeiten. Dazu müssen weitere automatisierte Tests hinzugefügt werden, die die Interaktion zwischen den “Black Boxes” betreffen, und sie müssen so häufig wie möglich durchgeführt werden.

Continuous Integration System

In der Regel wird ein Werkzeug namens “Continuous integration system” verwendet, um dies zu automatisieren. Wenn ein Code-Repository aktualisiert wird, erstellt das Continuous-Integration-Tool einen Software-Build aus der aktuellen Codebasis, installiert alle Abhängigkeiten und bereitet die Testumgebung vor, führt alle automatisierten Tests und Prüfungen sowohl auf Unit- als auch auf Systemebene durch und erstellt als Ergebnis einen Testbericht für die Entwickler. Normalerweise beinhaltet dies auch die Messung der “Codeabdeckung” und die Suche nach Code-Style-Problemen. Manchmal aktualisiert dieses Tool auch die Instanzen der Webanwendung, die für die interne Entwicklung und Demonstration verwendet werden. Der Kerngedanke ist jedoch, dass jede veröffentlichte Codeänderung den gesamten Prozess auslösen sollte, um sicherzustellen, dass alle potenziellen Probleme so schnell wie möglich behoben werden.

Stress-/Penetrationstests

Bei größeren Anwendungen wird nicht nur sichergestellt, dass diese bei normalen Geschäftsabläufen wie erwartet funktioniert, sondern es werden auch Stress-/Penetrationstests durchgeführt, um die Stabilität in Situationen höherer Gewalt zu gewährleisten. In der Regel wird dies für Webanwendungen durchgeführt und es werden verschiedene Tools verwendet, um Extremsituationen zu simulieren: hohe Benutzeraktivität, DDoS-Angriffsversuche, ein Hacker/Script-Kiddie, der einen neuen Exploit verwendet, um die Anwendung abzuschalten usw. Diese Situationen zu imitieren, erfordert viel Aufwand und Wissen: Dafür gibt es spezielle Fachleute, die dafür zuständig sind. Wenn jedoch ein Entwicklerteam den Webanwendungsserver regelmäßig aktualisiert (in Bezug auf externe Abhängigkeiten), sollte er in 99,999 % der Fälle sicher sein.

Was können Sie als Kund:in im Hinblick auf Softwaretests besser machen?

1. Scheuen Sie sich nicht, in Softwaretests zu investieren, damit steigern Sie auch die Qualität Ihrer Webanwendung.

2. Unterstützen Sie die Entwickler, indem Sie so viele Testfälle wie möglich bereitstellen.