Hi, herzlich willkommen in dieser Lektion, in der wir uns mit den Fallstricken von Test-Strategien beschäftigen.

Welcher Inhalt wird in dieser Lektion behandelt?

Wir sprechen in den nächsten Minuten über

  • das Test-Fall-Objekt (auch Test Case genannt),
    • Test-Fälle,
    • Test-Aktionen,
    • Test-Ziele,
    • Test-Ergebnisse,
    • Test-Ketten,
    • Test-Reihen,
    • Test-Läufe und
    • Test-Vorlagen,
  • manuelles und automatisches Testen,
  • die zwei grundlegenden automatischen Test-Methoden,
  • den Einfluss von Test-Daten auf die Test-Strategie,
  • Positiv- und Negativ-Testen,
  • die Berücksichtigung von älteren Bestandsdaten beim Testen,
  • wie wir mit der kontinuierlich wachsenden Anzahl an Test-Fällen umgehen,
  • die Organisation von Test-Vorlagen,
  • die Auswirkung der Test-Strategie auf die Sprint-Planung und die Team-Besetzung,
  • die Konfigurationsstrategie,
  • das Resultat einer Strategie auf die Produktqualität,
  • und wir schauen uns letztendlich auch die finanzielle Auswirkung einer dauerhaft erfolgreichen Test-Strategie gegenüber typischen Fehlentwicklungen an.

Vorab wieder die Definition von Fachbegriffen in dieser Lektion:

Was ist eine GUI?

Eine GUI ist ein Graphical User Interface, also der Bildschirminhalt einer Softwareanwendung, die ein Software-Anwender zur Nutzung der Software angezeigt bekommt. Der Bildschirminhalt (sprich: die GUI) hat verschiedene Elemente zur Anzeige und Eingabe wie z.B. Listen, Menüs, Buttons, Eingabefelder usw.

Was ist eine Exception?

Exceptions (wörtlich übersetzt: Ausnahmen) sind Situationen, in denen das Programm nicht wie gewünscht weiterläuft. Für diese Ausnahmen bedarf es Lösungen im Programmcode, die dann greifen, wenn ein Anwender oder der Code an sich eine unpassende Aktion ausführt. Das Exception-Handling verhindert mit einer Lösungsoperation nicht nur einen Programmabsturz, sondern gibt dem Anwender anhand einer Nachricht auch einen Hinweis zur korrekten Durchführung einer Aktion.

Was ist Dev?

Mit „Dev“ (wie Development) bezeichnet man Entwicklungseinheiten, die sich unterhalb der Programm-Ebene in Teams organisieren.

Was ist Ops?

Mit „Ops“ (wie Operations) bezeichnet man Einheiten zum Betrieb einer Anwendung. DevOps ist eine Organisationsform, bei der Dev und Ops als eine Einheit mit gemeinsamer Organisationsstruktur zusammenarbeiten.

Was ist ein Bug?

Ein Bug ist ein Fehler bei der Programmierung oder Konfiguration einer Anwendung, der zu einem Ergebnis führt, das nicht der Anforderungserwartung entspricht.

Was ist eine Produktiv-Instanz?

Eine Produktiv-Instanz ist die Hard- und Software-Infrastruktur, die zum Alltagsbetrieb einer Anwendung erforderlich ist.

Was ist eine Test-Instanz?

Eine Test-Instanz ist die Hard- und Software-Infrastruktur, die zum Testen einer Anwendung erforderlich ist.

Nun aber zum Inhalt dieser Lektion:

Wie sieht der Lebenszyklus eines Testfalls aus?

Beginnen wir erst einmal mit etwas ganz Grundsätzlichem: im Gegensatz zu fast allen anderen Anforderungsobjekten, die in der Regel über einen Lebenszyklus z.B. vom „Backlog“ bis zu „Erledigt“ verfügen, haben Test-Fälle einen gänzlich anderen Lebenszyklus, nämlich:

  • „In Vorbereitung“
  • „Aktiv“
  • „Inaktiv“
  • und „Archiviert“.

Natürlich wird dieses Statusnetzwerk unternehmensindividuell erweitert, um die eigene Organisation abzubilden. Aber im Grunde sind es die zwei Statuswerte „Aktiv“ und „Inaktiv“, die Test-Fälle von fast allen anderen Anforderungsobjekten unterscheiden. Nur das „Non-Functional Requirement“-Objekt, das Herausforderungsobjekt im Value Stream und das Lösungsobjekt im Solution Train haben einen ähnlichen Lebenszyklus. Ein Test-Fall wird nach einem Test-Lauf nicht auf „Erledigt“ gesetzt, sondern mit dem Status „Aktiv“ immer wieder verwendet, bis der Test-Fall durch grundsätzliche Änderungen nicht mehr anwendbar und damit „Archiviert“ ist. Ein Test-Fall wird während seiner kontinuierlichen Wiederverwendung an neue Gegebenheiten angepasst, darf jedoch nie den ursprünglichen Zweck aus dem Auge verlieren. Im Fall eines erkannten Bugs wird ein Test-Fall auf „Inaktiv“ gesetzt, so dass er den weiteren Verlauf des Test-Laufs bis zur Beseitigung des Fehlers nicht unterbricht. Nach Beseitigung des Fehlers wird er wieder aktiviert. Selbst wenn ein Test-Fall aufgrund nicht mehr zutreffender Grundlagen archiviert wird, kann er bei wieder zutreffender Grundlage reaktiviert werden. Ein Test-Fall ist deshalb nie erledigt, sondern wird nur verwendet. Soweit zu dieser Grundlage.

Was ist eine Test-Aktion?

Ein Test-Fall beinhaltet mehrere Test-Aktionen, ein Test-Ziel und ein Test-Ergebnis. Wenn das Test-Ergebnis dem Test-Ziel entspricht, dann war der Test erfolgreich. Erfolglose Tests führen zur Ursachenuntersuchung und ggf. zur Erstellung eines Bugs.

Was ist eine Testkette?

Mehrere Test-Fälle können in einer Test-Kette aneinandergereiht werden, die einen Anwendungsfall (auch Use Case genannt) abbildet.

Was ist eine Testreihe?

Mehrere Test-Ketten können in einer Test-Reihe parallel eingerichtet werden. Mehrere Test-Reihen können dann in einem Test-Lauf gestartet werden. Ein Test-Lauf ist abgeschlossen, wenn die zeitlich längste Test-Kette erledigt ist. Bei einem kontinuierlichen Test kann der Test-Lauf direkt nach Abschluss automatisch neu gestartet werden.

Wie unterscheiden sich manuelles von automatischem Testen?

Nun zum Unterschied zwischen manuellem und automatischem Testen:

Beim manuellen Testen arbeitet ein Mensch einen Test-Fall nach dem anderen ab, indem er in der zu testenden Anwendung die im Test-Fall beschriebenen Arbeitsschritte ausführt und am Ende eines Test-Falls das definierte Ergebnis erreichen soll. Dieser Ablauf und der damit verbundene Aufwand muss mit jedem Test-Lauf wiederholt werden. Test-Läufe werden bei Unit-Tests pro Sprint, andere Test-Typen je nach Test- und Deployment-Strategie pro Release durchgeführt. Im Extremfall gibt es beim Continuous Deployment, das vor allem bei standardisierten Cloud-Lösungen eingesetzt wird, kontinuierliche Test-Läufe, die in Endlosschleife ablaufen. Dass in solch einem Fall manuelles Testen schnell in die Sackgasse führt, wird glaube ich jedem schnell klar. Die Sackgasse bedeutet in der Realität, dass ein Test-Fall im Gegensatz zu seinem Sinn nur ein Mal durchgeführt und nicht wiederholt wird. Manuelles Testen wird heute hauptsächlich dort eingesetzt, wo ein hoher Testaufwand mit einer begrenzten Nutzerzahl verbunden ist, Korrekturen intern schnell realisiert werden können und Qualitätsmängel keinen Imageschaden bei Kunden anrichten können. Das betrifft heute vor allem unternehmensinterne Anwendungen – auch in Großunternehmen mit mehreren tausend Anwendern. Dazu kommen Anwendungen in Endprodukten. Und das war bisher auch ein adäquater Weg. Seitdem Endprodukte aber immer mehr Elektronikanteile und damit auch mehr Software beinhalten, funktioniert der bisherige Weg nicht mehr. Und so kommt es, dass Unternehmen den bisherigen Weg nicht nur aufgrund eigener Qualitätsanforderungen in Frage stellen, sondern auch regulatorische Anforderungen eine Umorientierung erzwingen.

Und damit kommen wir dann auch schon zum automatischen Testen. Beim automatischen Testen richtet ein Mensch den Test-Fall einmalig in einem Test-Management-System und einem Test-Execution-System ein. Diese Einrichtung erfordert eine deutlich höhere fachliche Qualifikation und dauert auch länger als die Einrichtung eines manuellen Test-Falls in einem Test-Management-System. Die hierfür notwendige Qualifikation ist rar und deshalb teuer – vor allem wenn für Leitungsaufgaben zwingend notwendige Erfahrungen vorausgesetzt werden. Zudem ist für das automatische Testen eine Test-Infrastruktur notwendig, die wesentliche einmalige Investitionen und laufende Kosten verursacht. Dieser Nachteil amortisiert sich jedoch schnell, weil die Ausführung der Tests keinen weiteren manuellen Aufwand erzeugt und damit flexibel und kosteneffizient skaliert werden kann.

Welche Ansätze gibt es für das automatische Testen?

Beim automatischen Testen gibt es zwei unterschiedliche Ansätze:

GUI-basierende Test-Automatisierungen nutzen einen Rekorder, der Arbeitsschritte in Form von Tastatureingaben und Mausaktionen in der Anwendung aufzeichnet und diese Aufzeichnung dann im Test-Lauf in der aktuellen Entwicklungsversion abspielt. Dieser Automatisierungsansatz ist einfach einzurichten und ebenso einfach zu nutzen. Allerdings hat dieser Ansatz einen großen Haken: Mausaktionen werden mit Pixelreaktionen auf dem Bildschirm aufgezeichnet und an genau diesem Pixel wieder abgespielt. Wenn sich nun die Bildschirmauflösung ändert, dann wird die aufgezeichnete Aktion an ganz anderer Stelle ausgeführt und der Test-Fall erzeugt einen Fehler. Auch wenn sich die Position eines GUI-Elements aufgrund eines Re-Designs oder einer Ergänzung ändert, läuft der Test-Fall ins Leere, weil sich am aufgezeichneten Pixel kein Eingabeelement mehr befindet. Das führt in der Praxis dazu, dass bestehende Elemente wegen dem hohen Aufwand in die Anpassung von Test-Fällen nicht angetastet werden und sich deshalb die Lösungsentwicklung stark einschränkt und damit suboptimale Lösungen liefert. Aber nicht nur Mausaktionen sind hier problematisch. Auch Tab-Aktionen von einem Eingabefeld zum Nächsten führen nicht zum Ziel, wenn ein zusätzliches Eingabefeld in die Abfolge eingefügt wird. Auch in diesem Fall müssen alle Test-Fälle überarbeitet werden oder die Abfolge des neuen Eingabefelds suboptimal ans Ende der Sequenz gesetzt werden. Als Fazit bleibt zu sagen: GUI-basierendes Testen ist günstig und einfach umzusetzen, aber ungenügend beim Ergebnis und der Pflege – vor allem bei langfristiger Betrachtung, der Berücksichtigung der Nutzerfreundlichkeit und dem Bedarf fortwährender Anpassung bestehender Test-Fälle bei Änderungen in der GUI.

Und da, wo es ein Problem gibt, da gibt es oft auch eine professionelle Lösung: Mit schnittstellenbasierenden Lösungen zur Test-Automatisierung gibt es keine Abhängigkeiten von einer GUI, weil der Test-Fall über die Schnittstelle zwischen Test-Managementsystem und der zu testenden Anwendung ohne GUI-Interaktion auskommt. In der Regel wird dafür die REST- oder SOA-Schnittstelle einer Anwendung genutzt. Die Test-Aktionen eines Test-Falls werden hierbei direkt im Code der Anwendung ausgeführt. Aber die Einrichtung und Pflege solcher Test-Fälle erfordert die bereits erwähnte hohe Qualifikation sowie das Vorhandensein einer Schnittstelle mit entsprechender Dokumentation.

Wie wird Software mit Statusnetzwerken getestet?

Jetzt könnten wir uns sagen: hey prima! Lösung da. Nehmen wir an, dass wir auch die notwendigen Personalressourcen mit ausreichend Qualifikation und Erfahrung gefunden haben. Und ein Test-Managementsystem mit Anbindung an ein gutes Werkzeug zur Test-Automatisierung haben wir auch. Können wir also loslegen. Ja, im Grunde schon. Aber leider ist nicht eine zu testende Anwendung wie die andere. Jede zu testende Anwendung ist ein einzigartiges Test-Projekt, das eine individuelle Test-Strategie erfordert – oder zumindest die Anpassung einer unternehmensweiten Test-Strategie.

Bei ERP-, PLM- und ALM-Systemen bewegen sich Objekte typischerweise durch ein Statusnetzwerk, z.B. von „Neu“ über „In Vorbereitung“, „In Bearbeitung“, „In Prüfung“ bis zu „Freigegeben“ und „Archiviert“. Wenn wir jetzt Objekte mit dem Status „Neu“ durchtesten, dann stehen diese Objekte für den nächsten Test-Lauf nicht mehr mit dem Ursprung-Status, sondern nur noch mit dem Ergebnis-Status zur Verfügung. Uns geht also mit jedem Test-Lauf die Test-Grundlage verloren, während sich auf der anderen Seite immer mehr Objekte mit einem fortgeschrittenen Status ansammeln. In diesem Beispiel könnten wir das Test-Objekt nur noch verwenden, um den Schritt zur Archivierung durchzuführen. Auf einen Lösungsansatz dazu möchte ich in einigen Minuten eingehen.

Was ist Positiv-Testing und Negativ-Testing?

Eine weitere Herausforderung ist, dass nicht nur der ideale Weg zum Erreichen eines Ziels, sondern auch alle erdenklichen Fehleraktionen eines Anwenders und die dafür notwendigen Rückmeldungen getestet werden sollten. Was bringt dem Anwender ein positives Test-Resultat, wenn bei jeder Aktion, die nicht dem Ideal des Entwicklers entspricht, die Anwendung abstürzt oder eine fehlerhafte Folgeaktion ausgelöst wird? Das kann nicht das Ziel von Tests sein! Also gehören zum Testen neben den Positiv-Tests eine Vielzahl von Negativ-Tests. Ein guter Anhaltspunkt sind durchschnittlich 5 Negativ-Test-Fälle pro Positiv-Test-Fall. Mindestens. Das Verhältnis ist je nach Anwendung sehr unterschiedlich. Je mehr Test-Aktionen es in einem Test-Fall gibt und je mehr Optionen es bei der Durchführung eines Test-Falls gibt, desto mehr negative Test-Fälle sind notwendig, um die fehlerfreie Funktion gewährleisten zu können. Das können dann auch schon mal 50 Negativ-Test-Fälle oder mehr pro Positiv-Test-Fall werden, wenn alle Kombinationen an Fehlermöglichkeiten überprüft werden. Diesem Ideal steht allerdings oft der Geldbeutel gegenüber, so dass sich die Definition der Negativ-Test-Fälle auf die gängigsten und absehbarsten Fehlerquellen beschränkt. Zudem ist es so, dass ein guter Anwendungsentwickler bereits alle notwendigen Exceptions berücksichtigt und bereits Lösungen zum Abfangen von Programmabstürzen und damit zusammenhängende Nachrichten an den Anwender eingebaut hat. Aber: niemand ist perfekt und deshalb gehören Negativ-Test-Fälle in jede Test-Strategie mit dem Ziel einer qualitativ hochwertigen Anwendung.

Wenn wir nun davon ausgehen, dass in einem Unternehmen für eine einzelne Softwareanwendung pro Jahr nur 1.000 Anforderungen (sprich: User Stories) umgesetzt werden, jede Anforderung 3-5 Akzeptanzkriterien hat, diese mit Positiv-Test-Fällen abgesichert werden und pro Positiv-Test-Fall 5 Negativ-Test-Fälle eingerichtet werden, dann kommen wir schnell in eine enorme Anzahl von Test-Fällen pro Jahr – für nur eine Anwendung. Und davon hat ein Großunternehmen ja doch einige Hundert. Bedenke bitte auch, dass wir bei dieser Betrachtung noch keine Test-Fälle für Risiken berücksichtigt haben! Im Endeffekt sprechen wir in einem Unternehmen nach 10 Jahren von 20-50 Mio. laufenden Test-Fällen! Nun gut, einige davon fallen mit der Zeit wieder raus und nicht für jede Anforderung müssen alle Positiv- und Negativ-Test-Fälle neu angelegt werden. Oft können wir bestehende Test-Fälle erweitern. Aber letztendlich bleibt es bei einer riesigen und exponentiell ansteigenden Anzahl von Test-Fällen, die mit einer langfristig funktionierenden Test-Strategie bewältigt werden muss.

Wie werden Bestandsdaten getestet?

Mit dieser Menge ist die Fahnenstange aber noch lange nicht erreicht! Wir gehen bisher davon aus, dass nur mit neuen Daten (sprich: Bestandsdaten einer einzigen Generation oder Version) getestet wird. Die Datenstruktur entwickelt sich jedoch im Laufe von Versionen weiter. Das Ziel muss also sein, dass ein Anwender auch mit den Daten der Vorversion und noch älteren Bestandsdaten fehlerfrei arbeiten können muss – egal ob es sich um Migrationsdaten oder unveränderte Altdaten handelt. Diese Test-Fälle haben wir bisher noch gar nicht berücksichtigt. Im Grunde ist die Rechnung aber einfach: die bereits berechnete Anzahl an Test-Fällen wird mit der Anzahl der unterstützten Vorversionen multipliziert. 5 unterstützte Vorversionen ergeben bei zuvor genannter Rechnung also 100-250 Mio. Test-Fälle. Wowww! Und die wollen strukturiert organisiert und gepflegt sein, um die Anzahl und den damit zusammenhängenden Rechenaufwand (sprich: die Test-Laufzeit und die dafür benötigte Infrastrukturkapazität) in Grenzen zu halten.

Die Frage ist nur wie?

Wie kann der Aufwand für automatisches Testen reduziert werden?

Im Grunde gilt es Test-Fälle, Test-Ketten und Test-Reihen in einer übersichtlichen Struktur zu klassifizieren und dann für jeden Test-Fall einer Klasse eine standardisierte Vorlage zur Verfügung zu stellen. Damit bekommt der Test-Manager einen Überblick, an welchen Stellen und in welcher Form ein neuer Test-Fall gefunden, ergänzt und gepflegt wird. Und ja: bei einer umfassenden Test-Strategie wie zuvor beschrieben, bedarf es einen Test-Fall mehrfach an den richtigen Stellen in das bestehende System einzupflegen. Um hierbei den Überblick zu behalten und sauber zu arbeiten, braucht es eine ganz besondere Qualifikation aus technologischer Kompetenz und sauberer sowie strukturierter Arbeitsweise. Die Anforderung eines agilen Teams nach Aufgabenrotation und Wissensverbreitung im Team ist mit diesen sehr speziellen Qualifikationen schwer umsetzbar – und trotzdem sollten Test-Manager Bestandteil des agilen Entwicklungsteams bleiben, weil nur dann sichergestellt werden kann, dass die Test-Fälle im Sinne der Kundenanforderungen eingerichtet werden. Wenn ein Test-Manager im Team aber die alleinige Zuständigkeit hat, dann ist die Abhängigkeit und der Leistungsdruck groß. Vor allem im Krankheits- und Urlaubsfall wäre keine Einrichtung oder Pflege von Test-Fällen möglich. Und bei einem Komplettausfall wäre das Wissen verloren. Geht also gar nicht! Die Redundanz im Team ist teuer und ggf. nicht voll ausgelastet. Das ist für das Projektbudget also auch schwer vermittelbar. Bleibt die Ausgliederung in eine Tester-Einheit, welche die notwendige Kapazität zentral zur Verfügung stellt und trotzdem möglichst eng mit den Entwicklungsteams zusammenarbeitet, um verstehen zu können, in welchem Anwendungsbereich sich der jeweilige Test-Fall befindet. Ein weiterer Vorteil, der sich damit ergibt, ist die Vereinheitlichung der Test-Strategie über alle Bereiche, Lösungen, Programme und Teams hinweg. Und das ist es auch, was ich den meisten Unternehmen vorschlagen würde. Eine Tester-Organisation, die sich zwischen Dev und Ops einrichtet und damit eng mit beiden Bereichen zusammenarbeitet.

Wie werden negative Testergebnisse behandelt?

Wenn wir die enorme Anzahl an Test-Fällen betrachten, dann ist für uns alle leicht vorstellbar, dass sich bei der Weiterentwicklung einer Anwendung eine Menge an negativen Test-Resultaten ergibt. Die Frage ist: wie gehen wir damit um? Missachten? Dann war der ganze Aufwand für die Katz und wir hätten uns das Geld sparen können. Jedes negative Test-Resultat untersuchen und abhängig von der Ursache den Test-Fall anpassen oder einen Bug melden und vorübergehende Deaktivierung des Test-Falls? Das kostet eine Menge Zeit, aber ja: das muss die notwendige Konsequenz sein, um die Qualität einer Anwendung zu gewährleisten. Und das dafür notwendige Budget muss in einem Projekt eingeplant werden. Heutzutage lässt sich die Bugmeldung automatisieren, indem der Test-Fall deaktiviert und ein Bug-Objekt im Backlog des hinterlegten Entwicklungsteams erzeugt wird. Bei solch umfassenden Test-Strategien liegt die Ursache für negative Test-Resultate allerdings überwiegend an notwendig gewordenen Anpassungen der Test-Fälle. Das Entwicklungsteam würde also mit Aufgaben überschwemmt werden, die dann doch wieder an die Tester-Einheit zurückgeleitet wird. Diesen teuren und unsinnigen Aufwand können wir uns dann doch sparen und die Bearbeitung in der Tester-Einheit belassen, die dann nur im zutreffenden Fall Bug-Meldungen für die zuständige Entwicklungseinheit erstellt.

Wie hoch ist der Aufwand für das Bugfixing?

Eine weitere Herausforderung ist die Abarbeitung von Bugs in den Sprints der Entwicklungsteams. Bis heute ist es üblich, dass Bugs kategorisiert und priorisiert werden und immer dann abgearbeitet werden, wenn in einem Sprint nach Abarbeitung der zugeteilten Anforderungen noch Kapazität frei ist. Das Resultat? Kennen wir doch alle: nur die schlimmsten Bugs werden beseitigt, alle anderen verschimmeln im Backlog und führen zu Folgefehlern in der Anwendung, die nicht selten negative Auswirkungen auf die Anwendungsarchitektur haben und eine Anwendung so undurchsichtig machen, dass keiner mehr durchblickt. Besser sieht es in Unternehmen aus, die einen festen Kapazitätsanteil pro Sprint für die Bug-Bearbeitung einplant. Aber auch hier verschimmelt der Großteil der Bugs im Backlog. Die schiere Menge an Bugs, die sich aus einer umfassenden Test-Strategie ergibt, ist in diesem Rahmen auf keinen Fall mehr abzuarbeiten. Und wenn Bugs nicht abgearbeitet werden, dann wird das Ziel einer umfassenden Test-Strategie nicht erreicht. Sprich: auch hier können wir uns dann den gesamten Aufwand sparen und akzeptieren lieber die Konsequenz, dass wir schlechte Qualität liefern und regulatorische Vorgaben nicht erfüllen und damit in letzter Konsequenz aus dem Markt ausscheiden. Ach so: nein, das geht dann ja auch nicht. Also bleibt nur die konsequente Abarbeitung von Bugs. Die Lösung, die sich bisher am meisten bewährt hat, ist ein Bug-Sprint zwischen mehreren Dev-Sprints. Das Verhältnis von 3:1 hat sich ganz gut bewährt, ist aber auch stark von jedem Unternehmen abhängig. Auch dieses Budget muss in einem Projekt und Programm eingeplant sein. Von nichts kommt nichts, auch wenn es Vorgesetztenebenen oder Einkaufsabteilungen gerne so durchsetzen möchten. Logik ist spätestens bei der Umsetzung nicht mehr verbiegbar.

Welche Teststrategie passt zum Projekt?

Kommen wir nun zu einem der wichtigsten Punkte für die Test-Strategie – meiner Meinung nach sogar zum wichtigsten Punkt, weil hierin das größte Potenzial für den Erfolg und Misserfolg steckt. Mit Misserfolg meine ich vor allem die negativen Kostenauswirkungen, wenn die Strategie in die Sackgasse geführt hat. Ich spreche hier genau gesagt von der Konfigurationsstrategie einer Test-Umgebung.

Stelle Dir im einfachsten Fall vor, dass Du einen Test-Fall mit 3 Test-Aktionen, einem Test-Ziel und einem Test-Ergebnis hast. Dieser Test-Fall wird mit einem Test-Lauf gestartet. Ganz einfach. Kein Problem.

Nun hast Du aber, wie zuvor besprochen, nicht nur einen Test-Fall, sondern mehrere Test-Fälle. Wenn Du die hintereinander in einer Test-Kette konfigurierst und dann in einem Test-Lauf startest, dann wird der Test-Lauf extrem lange laufen – bei exponentiell zunehmenden Test-Fällen viel zu lange.

Hier nur ein Beispiel aus der Praxis: ein Automobilhersteller in Deutschland hat die ambitionierte Strategie, von heute 4 Releases pro Anwendung/Jahr (was nicht schlecht ist!) über monatliche, dann wöchentliche Releases das Ziel eines Continuous Deployment zu erreichen. Das bedeutet, dass über Prozessautomatisierungen Applikationsänderungen nach Durchlauf aller Schritte kontinuierlich als Funktionalität in den Anwendungen zur Verfügung gestellt werden. Für das Testen bedeutet das, dass die Test-Fälle nie und nimmer in einer langen Kette hintereinander abgearbeitet werden können.

O.k. Dann konfigurieren wir die Test-Fälle doch einfach alle parallel in Test-Reihen. Jeder Test-Fall in einer eigenen Test-Reihe. Und alle Test-Reihen packen wir in einen Test-Lauf. Der müsste dann ja in null Komma nix abgearbeitet sein. Das trifft so leider nur in der Theorie zu, denn stelle Dir vor: auf der Applikationsinfrastruktur werden alle Aktionen zeitglich ausgeführt. Da brauchst Du Rechenpower ohne Ende, die weit über den Leistungsanspruch an die Produktiv-Instanz hinausgeht – und zwar so viel, dass sie in der Realität nicht zur Verfügung gestellt werden kann. Die Test-Instanz schmiert sofort beim Test-Lauf-Start ab und wir haben damit leider gar nichts erreicht.

Da beide Extreme erwartungsgemäß nicht zielführend sind, erinnern wir uns an die zuvor angesprochene Arbeit mit Klassifizierung und Vorlagen. Unser Ziel muss dabei sein, die Test-Lauflänge so kurz zu halten, dass der unternehmensindividuelle Anspruch an die Release-Zeitpunkte eingehalten werden kann, gleichzeitig die Test-Infrastruktur nicht überfordert wird und sich die dafür notwendigen Kosten in Grenzen halten. Auch in diesem Punkt ergibt sich ein Budgetbedarf, der oft deutlich unterschätzt und damit unterbudgetiert wird. Wer denkt schon daran, dass die Test-Infrastruktur einen höheren Budgetbedarf als eine Produktivinstanz haben könnte?

Das Ziel unserer Bestrebung ist, komplette Anwendungsfälle (sprich: Use Cases) in einer Test-Kette abzubilden. Bei kurzen Anwendungsfällen können 2, 3 oder mehr Anwendungsfälle aneinandergereiht werden. Immer mit dem Ziel, die geplante Test-Lauflänge zu erreichen. Und weil sich Anwendungsfälle erfahrungsgemäß konstant erweitern, lieber mit einem ordentlichen Puffer, weil die Kette sonst mit Zusatzaufwand aufgeteilt werden muss. Auch das lässt sich leider nicht vermeiden und wird zu einer regelmäßigen Zusatzaufgabe werden. Zu viel Puffer können wir uns aber auch nicht erlauben, weil sonst die Anforderungen an die Test-Infrastruktur zu groß werden und die teure Infrastruktur wirtschaftlich nicht ausgenutzt wird.

Das Idealergebnis ist ein geschlossener Block von Test-Ketten und Test-Reihen, der die Infrastruktur möglichst gut ausnutzt und trotzdem noch Erweiterungspuffer beinhaltet. In diesem Zusammenhang haben sich flexibel erweiterbare Cloud-Angebote bewährt, wenn Sicherheitsaspekte dies zulassen.

Und jetzt fangen wir wie bereits zuvor mit den Anforderungserweiterungen an:

Wenn wir Datenobjekte mit einem sich verändernden Statusnetzwerk testen, dann müssen wir dem Test-Fall vorgelagert für jede Test-Kette erst einmal die dafür notwendigen Datenobjekte erstellen. Damit wir unsere Test-Infrastruktur nicht zumüllen, sollten wir diese Datenobjekte am Ende der Test-Kette mit Administrator-Rechten wieder löschen – falls die Anwendung das Löschen von Objekten überhaupt zulässt. Wenn wir das nicht entsprechend einrichten, dann haben wir recht schnell einen Berg von Datenobjekten mit einem fortgeschrittenen Status, der das Test-System überlastet und letztendlich mit manuellem Datenbankeingriff bereinigt werden muss. Besser ist deshalb auf jeden Fall die Säuberung am Ende einer Test-Kette.

Und wenn wir mit Test-Reihen arbeiten und ein User systembedingt nur einmal gleichzeitig Aktionen durchführen kann, dann müssen wir dem Test-Fall vorgelagert für jede Test-Reihe erst einmal die User der Test-Kette mit den notwendigen Rollen und Rechten erstellen. Innerhalb der Test-Ketten melden sich die erzeugten User im Test-Verlauf an und ab, um den gesamten Anwendungsfall abbilden zu können. Damit wir die Test-Infrastruktur nicht zumüllen, müssen wir die angelegten User am Ende der Test-Kette mit Administrationsrechten wieder löschen.

Wir erzeugen uns also für jede Test-Kette all die Test-Daten mit Statusnetzwerken selbst, die in der zu testenden Anwendung benötigt werden. Weitere Test-Daten, die über kein Statusnetzwerk verfügen, können wie in jeder anderen Anwendung dauerhaft verwendet werden. Na, das sieht jetzt doch gut aus, oder? Sagen wir mal: das war ein guter Einstieg!

Denn jetzt kommen ja noch die vielen Negativ-Test-Fälle pro Positiv-Test-Fall hinzu. Wir erweitern die bestehenden Test-Ketten also um die Negativ-Test-Fälle, indem wir vor jedem Positiv-Test-Fall die Negativ-Test-Fälle ergänzen. Auf die Art: falsch funktioniert nicht (sprich: erwartetes Test-Ziel des Negativ-Test-Falls ist erreicht), falsch funktioniert nicht, ahhh: richtig funktioniert, also kann es weiter gehen. Damit erweitert sich die bisherige Test-Kette gut und gerne um den Faktor 5. Das ist bereits bei der Einrichtung der Positiv-Test-Kette zu berücksichtigen, oder die Test-Kette wird von Anfang an mit allen Negativ- und Positiv-Test-Fällen eingerichtet. Aber Vorsicht: die Negativ-Test-Fälle werden konstant durch die Erfahrungen aus der Anwenderbetreuung, aus Beschwerden, dem Risikomanagement und regulatorischen Ergänzungen erweitert. Nun, jetzt sieht es doch richtig gut aus, oder? Sagen wir mal: das ist jetzt ein guter Zwischenstand!

Denn bisher arbeiten wir ja nur mit den neuesten Bestandsdaten. Wir brauchen jetzt noch eine definierte Anzahl an Vorversionen, deren darin erzeugte Bestandsdaten mit der neuesten Version getestet werden müssen. Der Ablauf ist recht simpel und gar nicht so aufwendig. Die dafür notwendigen Test-Ketten und Test-Reihen müssen ja nicht noch einmal manuell erzeugt werden, sondern können einfach kopiert werden, so dass diese auf die jeweils zugeordneten älteren Bestandsdaten zugreifen. In manchen Fällen ist es sogar sinnvoll, für jeden Datenbestand eine eigene Test-Instanz aufzusetzen – das hängt immer von der Architektur der zu testenden Anwendung ab.

Welche Vorteile bietet eine strukturierte Teststrategie?

Soweit also zur Konfigurations-Strategie. Das Ergebnis berücksichtigt den exponentiellen Anstieg der Test-Fälle und die Leistungsgrenzen der Test-Infrastruktur. Mit solch einer umfassenden Test-Strategie werden die regulatorischen Ziele und die Qualitätsziele erreicht. Der Personal-, Investitions- und Betriebsaufwand hält sich trotz der enormen Anzahl an Test-Fällen in Grenzen. Die schiere Menge an Test-Fällen wird durch Klassifizierung und ein Vorlagensystem zumindest übersichtlicher gemacht, wenn auch dafür – wie besprochen – ganz besondere Kompetenzen gefragt sind. Die Sackgassensituation wie beim manuellen Testen wird dauerhaft vermieden. Und die Test-Dauer lässt sich durch Anpassung der Test-Ketten an den Release-Intervall anpassen.

Ist solch eine durchdachte Test-Strategie alternativlos? Ich meine ja, weil jedes gewachsene Konstrukt ohne diese Betrachtungen in eine Sackgasse führt. Sei es die Nichterreichung der Ziele oder die Unbezahlbarkeit der Anforderungen. Auf mögliche Fehlentwicklungen dazu sind wir im Verlauf dieser Lektion bereits eingegangen.

Ist die hier geschilderte Test-Strategie das Allheilmittel für alle Unternehmen? Dazu sage ich ganz klar: nein! Jedes Unternehmen ist individuell, genauso wie seine Organisation, Produkte und Anwendungen. Im Grunde bedarf es einer genauen Betrachtung der Unternehmensorganisation, der Produkte und der Architektur der Anwendungen sowie einen kühnen Ausblick in die Zukunft des Unternehmens, um die passende Test-Strategie zu erarbeiten. Die von mir im Verlauf dieser Lektion gestellten Überlegungen können dabei als Anhaltspunkt dienen, aber sie sind beileibe keine Blaupause.

Fassen wir nun zusammen, was wir in dieser Lektion behandelt haben:

  • wir haben uns mit dem Test-Fall-Objekt beschäftigt,
    • uns Test-Fälle,
    • Test-Aktionen,
    • Test-Ziele,
    • Test-Ergebnisse,
    • Test-Ketten,
    • Test-Reihen,
    • Test-Läufe und
    • Test-Vorlagen angesehen,
  • über den Unterschied sowie die Vor- und Nachteile des manuellen und automatischen Testen gesprochen,
  • die zwei grundlegenden automatischen Test-Methoden kennengelernt,
  • den Einfluss von Test-Daten auf die Test-Strategie betrachtet,
  • wir haben die notwendige Ergänzung von Positiv- durch Negativ-Tests erkannt,
  • die Notwendigkeit der Berücksichtigung von älteren Bestandsdaten beim Testen kennengelernt,
  • haben uns eine Lösung zum Umgang mit der kontinuierlich wachsenden Anzahl an Test-Fällen angesehen,
  • wir haben erkannt, dass sich die Test-Strategie auf die Sprintplanung und die Team-Besetzung auswirken kann,
  • haben uns etwas umfassender mit der Konfigurationsstrategie beschäftigt,
  • das Resultat einer Strategie auf die Produktqualität erkannt,
  • und wir haben uns im gesamten Verlauf der Lektion mit möglichen Fehlentwicklungen und deren Auswirkungen auseinandergesetzt.

In der übernächsten Lektion steigen wir etwas tiefer in das Thema Testen ein und betrachten uns die Unit Tests. Doch zuvor gibt es für Dich eine kleine Überraschung:

Die folgende Lektion beinhaltet ein kurzes Quiz, bei dem Du für Dich selbst prüfen kannst, welche Inhalte aus dieser Lektion bei Dir hängengeblieben sind. Ich wünsche Dir viel Spaß dabei, wir sehen uns in der übernächsten Lektion wieder!

Kommentar verfassen