Wohin mit den Testfällen?

Oct 22
2009

Am Ende jedes Testzyklus stellt sich die entscheidende Frage: Ist das Produkt in Ordnung?

Diese Frage kommt manchmal auch mit einem entsprechend vorwurfsvollen Unterton, wenn gerade ein Fehler entdeckt wurde, der in den internen Tests nicht gefunden wurde. Wie kann ich also meine eigene Einschätzung über ein Software Produkt plausibel darlegen?

Dafür brauche ich Anworten auf drei Fragen:

  • Welche Testfälle gibt es?
  • Was decken diese Testfälle ab?
  • Was sind die Durchführungsresultate dieser Tests?

Um diese Fragen beantworten zu können, brauche ich die entsprechenden Daten, um das zu belegen.

Welche Testfälle gibt es?

Die Testfälle müssen abgelegt werden. Ein Testfall, der nicht dokumentiert ist, ist wenig wert. Allfällig gefundene Probleme sind häufig nicht reproduzierbar. Er kann kein zweites Mal ausgeführt werden. Da aber gerade in iterativ inkrementellen Entwicklungsprozessen die Aufwände und Überlegungen zur Erstellung eines Testfalls sich erst bei einer wiederholten Ausführung auszahlen – am Ende jeder Iteration oder vielleicht noch häufiger – ist das eine schlechte Investition.

Die Testfälle sollen in einem definierten Format mit bestimmten Attributen dokumentiert und abgelegt werden. Je nach Kontext des Projekts gibt es für diese Ablage verschiedene Varianten – von einer Sammlung von Word Dokumenten über eine einfache Datenbank bis zu schwergewichtigen Testingwerkzeugen, in denen der gesamte Testingablauf abgebildet ist. Aus meiner Sicht muss eine solche Ablage einige Kriterien erfüllen:

  • Gut durchsuchbar: Gibt es zu dieser Thematik bereits Testfälle? Welche? Was für Testfälle sind in dieser Iteration neu dazugekommen?
  • Versionierbar: Was hat sich an diesem Testfall geändert? Wer hat die Änderung vorgenommen? Wann wurde der Testfall das letzte Mal angepasst? Wie kann ich mir eine alte Version besorgen?
  • Anpassungsfähig: Kann ich zusätzliche Attribute hinzufügen, die bei einem Testfall ausgefüllt werden müssen oder unnötige entfernen?
  • Navigierbar: Was sind die konkreten Testfälle zu diesem logischen Testfall? Welche logischen Testfälle haben noch keine konkreten Instanzierungen.

Wenn diese Eigenschaften gegeben sind, bin ich in der Lage, auf die erste dieser kritischen Fragen, “Welche Tests gibt es?”, eine differenzierte Antwort zu geben.

Was decken die Tests ab?

Abdeckung wird im Software Testing Umfeld meist technisch verstanden: Wieviel Prozent der Sourcecodeinstruktionen, Abzweigungen, etc. werden bei einem Test durchlaufen? Auch Wikipedia beschränkt sich unter dem Stichwort “Testabdeckung in der Softwaretechnik” auf dieses technische Mass. Die nackte gemessene Coveragezahl sagt aber wenig aus und ist nicht leicht zu interpretieren.

Abdeckung kann aber auch ganz anders verstanden werden. Ich betrachte die fachliche Abdeckung hier als erheblich hilfreicher. Wieviel Prozent der Abnahmekriterien sind abgedeckt? Zu welcher Businessrule hat es wieviele Testfälle?

Um Antworten auf diese Fragen geben zu können, müssen die Testfälle auf die Anforderungen gemappt werden. Es braucht die entsprechenden Attribute und sie müssen ausgefüllt und gepflegt werden. Diese Zusatzinformationen sind über die oben gestellte Frage hinaus auch extrem hilfreich bei Änderungen an den Anforderungen. Eine geänderte Regel muss Auswirkungen auf die Testfälle haben. Aber auf welche? Nur mit dieser Verknüpfung zwischen Testfällen und den Anforderungen, welche der Testfall überprüft, kann können diese Auswirkungen in die richtigen Testfälle eingearbeitet werden.

Was sind die Durchführungsresultate dieser Tests?

Die Information, welche Testfälle es gibt, kann noch keine Aussage über die Qualität des Produkts geben. Entscheidend ist die Frage, welche Tests wann, wie und mit welchem Resultat durchgeführt wurden. Erst die Testresultate geben Aufschluss darüber, wie der Zustand des Systems ist.

Jede Durchführung eines Testfalles muss unbedingt protokolliert werden. Neben den offensichtlichen Resultaten – success oder failure – ist gerade auch die Aussage, dass ein Testfall nicht durchgeführt werden konnte, ebenfalls interessant. Es muss also auch möglich sein, eine Ausführung als “nicht durchführbar” zu protokollieren, analog zum “Ignored” Flag bei JUnit.

Um nicht nur die manuellen Ausführungen zu protokollieren, sondern auch die automatische ausgeführten Tests, brauche ich hier eine geeignete Schnittstelle, an die ich meine TestDriver anbinden kann.

Auch bei den Ausführungsresultaten ist es hilfreich, wenn diese Informationen in einer Form abgelegt werden, die eine Suche gut unterstützt. Welche Tests sind in dieser Woche fehlgeschlagen? Zu welchen Tests existiert noch keine erfolgreiche Durchführung? Welche Testfälle haben bereits mehrmals von “success” auf “failure” und wieder zurück gewechselt? Solche Auswertungen sollten je nach Bedarf definiert werden können.

Wenn ich zu diesen drei Fragen eine fundierte Antwort bereit habe und sie mit den entsprechenden Daten belegen kann, bin ich in der Lage zu argumentieren. Ich kann dann sagen, dass das Produkt mit grosser Wahrscheinlichkeit in einem guten Zustand ist, oder ich kann mich erklären, wieso die ins Testing investierten Resourcen eben doch sinnvoll eingesetzt sind, auch wenn ein Fehler nicht gefunden wurde und dann erst beim Kunden für entsprechenden Aufruhr sorgt…

Methoden zum Finden der “richtigen” Testfälle

Oct 21
2009

Die Erstellung der Testfälle ist sehr stark vom zu testenden System abhängig. Es gibt jedoch einige Methoden, die sich für das Blackbox Testing besonders gut eignen und auf viele konkrete Settings anwendbar sind. Die bekanntesten sind die Folgenden:

  • Äquivalenzklassenbildung und Grenzwertanalyse
  • Zustandsbezogener Test
  • Ursache-Wirkungs-Graph Analyse
  • Entscheidungstabellen

In diesem Kurs konzentrieren wir uns auf die erste dieser Methoden. Für die übrigen Methoden bietet [1] einen guten Überblick.

Schritt 1: Äquivalenzklassenbildung

Die Äquivalenzklassenbildung setzt bei der Problematik an, dass die Anzahl der möglichen Eingabewerte für eine bestimmte Funktionaliät in den allermeisten Fällen so enorm gross ist, dass es unmöglich ist, mit allen Werten zu testen. Die Grundidee dieser Methode ist es, dass die Menge der möglichen Eingabewerte in Klassen unterteilt wird. Zur gleichen Äquivalenzklasse gehören dabei jeweils alle Werte, von denen der Tester annimmt, dass sie die gleiche Wirkung erzielen bzw. dass sich das Testobjekt “gleich” verhält.

Diese Grundidee ist an sich nichts besonders Ausgefallenes. Die systematische Anwendung davon führt aber zu wichtigen Überlegungen über die zu testende Funktion und damit am Schluss zu sinnvoll ausgewählten Testfällen.

Beispiel 1

Die Posttarife für Pakete sind nach Gewicht abgestuft.
Aequ1
Äquivalenzklassenbildung Beispiel 1: Tabelle Pakettarife

Hier ergeben sich die Äquivalenzklassen automatisch. Ein Paket, das 2,5 kg schwer ist und eines das 2,7 kg schwer ist kosten beide 10.- und fallen damit in die gleiche Äquivalenzklasse.
Aequ3
Äquivalenzklassenbildung Beispiel 1: Triviale Äquivalenzklassen

Beispiel 2

Eine Funktion berechnet den Absolutwert einer Integerzahl.
Aequ2
Äquivalenzklassenbildung Beispiel 2: Code Absolutwertmethode

Hier ist die naheliegende Wahl der Äquivalenzklassen eine für die positiven und ein für die negativen Zahlen. Ob die Null einer der beiden Äquivalenzklassen zugeordnet wird oder eine eigene bildet ist Ermessenssache.
Aequ4
Äquivalenzklassenbildung Beispiel 2: Gewählte Äquivalenzklassen

Schritt 2: Grenzwertanalyse

Um nun ausführbare und wiederholbare Testfälle zu erhalten, müssen jetzt die konkreten Werte innerhalb der Äquivalenzklassen ausgewählt werden. Das Ziel jedes Testfalls ist es, mit einer möglichst grossen Wahrscheinlichkeit Fehler aufzudecken, sofern welche vorhanden sind. Die Werte, bei denen am häufigsten Fehler in der Implementierung auftreten, sind die Grenzwerte zwischen den Äquivalenzklassen. Es werden also als Vertreter der Äquivalenzklassen mit Vorteil diejenigen Werte gewählt, die an den Rändern der Äquivalenzklassen liegen. Für die beiden obigen Beispiele könnte das so aussehen:

Beispiel 1

Aequ5
Äquivalenzklassenbildung Beispiel 1: Konkrete Werte für Testfälle

Beispiel 2

Aequ6

Äquivalenzklassenbildung Beispiel 2: Konkrete Werte für Testfälle

Die Wahl der Äquivalenzklassen und der Grenzwerte ist selten so einfach und eindeutig, wie in diesen beiden Beispielen. In den meisten Fällen gibt es erheblichen Spielraum, was als eigene Äquivalenzklasse gezählt werden soll und welche Wertebereiche zusammengenommen werden. Diese Entscheidung hängt stark vom Testaufwand ab, der für eine bestimmte Funktionalität aufgewendet werden kann, da die Menge der effektiv auszuführenden Testfälle auf der Anzahl gewählter Äquivalenzklassen aufbaut.

Im folgenden Beispiel gibt es für die Wahl der Äquivalenzklassen verschiedene Granularitäten.

Beispiel 3

Eine Funktionalität soll für einen beliebigen Punkt P entscheiden, ob er innerhalb eines Rechtecks in einem Koordinatensystem liegt.
Aequ7

Äquivalenzklassenbildung Beispiel 3: Grafische Problemstellung

Für diese Problemstellung werden nun die Äquivalenzklassen gesucht. Dies wäre eine mögliche Wahl der Äquivalenzklassen:

Folie1

Äquivalenzklassenbildung Beispiel 3: Mögliche Wahl der Äquivalenzklassen

Häufig sind neben den durch das Problem definierten Abgrenzungen auch noch weitere Grenzen vorhanden, die zB durch die Problemstellung in den Wertebereichen inhärent vorhanden sind. In Beispiel 3 wären das zum Beispiel die Koordinatenachsen. Die Chance, dass bei der Implementierung der Regeln für diese Funktionalität ein Fehler bei negativen Koordinatenvorzeichen eingebaut wurde, wäre doch sicher nicht allzu klein.

Diese Beachtung der Eigenheiten des Wertebereichs ist oft sehr nützlich und kann Probleme aufdecken, die bei der ursprünglichen Wahl der Äquivalenzklassen übersehen würden.

Eine Wahl der Äquivalenzklassen unter Einbezug der Eigenheiten des Wertebereichs könnte so aussehen:
Folie2

Äquivalenzklassenbildung Beispiel 3: Wahl der Äquivalenzklassen unter Berücksichtigung der Grenzen des Wertebereichs

Damit wäre man aber bereits bei 16 verschiedenen Äquivalenzklassen, zu denen nun mittels Grenzwertanalyse Testfälle gefunden und anschliessend noch ausgeführt werden müssten. Ob sich dieser Aufwand rechtfertigen lässt, muss wieder anhand der bekannten Überlegungen zu erwarteter Wahrscheinlichkeit, dass diese Funktionalität fehlschlägt und dem Schaden, der dabei entstehen könnte, analysiert werden.

Im nächsten Schritt kommt nun die Wahl der konkreten Eingabewerte für die Testfälle mittels der Grenzwertanalyse, die in diesem grafischen Beispiel sehr anschaulich ist.
Folie3

Äquivalenzklassenbildung Beispiel 3: Wahl der Eingabewerte aufgrund Grenzwertanalyse

Strukurierung in logische und konkrete Testfälle

Auf Systemteststufe wird zwischen logischen und konkreten Testfällen unterschieden. Diese Unterscheidung ist nach den vorherigen Ausführungen über Äquivalenzklassenbildung und Grenzwertanalyse wenig überraschend.

Ein logischer Testfall ist die Spezifikation des Testablaufs und der zu überprüfenden Schritte ohne Angabe von konkreten Werten. Im logischen Testfall werden mit Wertekategorien und -bereichen gearbeitet. Die Annahme dabei ist, dass sich das System für alle Werte dieser Kategorie bzw. dieses Bereichs analog verhält. Im Fall der Testfallerstellungsmethode mittels Äquivalenzklassenbildung sind im logischen Testfall also die jeweiligen Äquivalenzklassen angegeben, nicht aber die konkreten Werte innerhalb der Klassen. Ein logischer Testfall kann deshalb nicht ausgeführt werden, weil es dafür die konkreten Werte braucht.

Ein konkreter Testfall ist eine Instanzierung des logischen Testfalls mit konkreten Werten. Damit ist der Testfall nun eindeutig spezifiziert und kann entsprechend ausgeführt werden. Der konkrete Testfall kann also das Resultat der Grenzwertanalyse zu den Kategorien sein, die im logischen Testfall festgelegt wurden.

Diese Strukturierung macht Sinn, sobald mit einer grösseren Anzahl von Testfällen gearbeitet werden muss. Sie erleichtern das Verständnis, weshalb in einem konkreten Testfall ein bestimmter Wert gewählt wurde und bringen eine Übersicht über die Menge der konkreten Testfälle. Falls sich zum Beispiel die Anforderungen an eine Funktionalität ändern, können die Auswirkungen auf der Ebene der logischen Testfälle nachvollzogen werden. Daraus ergibt sich dann direkt, welche konkreten Testfälle angepasst, neu erstellt oder weggeworfen werden müssen.

Qualitätseigenschaften von Testfällen

Oct 07
2009

Testen bedeutet ein systematisches Überprüfen des zu prüfenden Systems. Die Qualität der Testing Aktivitäten wird also wesentlich bestimmt durch die Frage, wie systematisch diese Überprüfung stattfindet.

Ein einzelnes Prüfszenario wird als ein Testfall bezeichnet. Ein Testfall soll ein bestimmtes Kriterium beleuchten und allfällige Probleme ans Tageslicht bringen. In diesem Kapitel geht es darum zu definieren, was einen guten Testfall ausmacht und wie solche Testfälle gefunden werden können.

Testfälle sind DER Rohstoff, auf dem sich ein erfolgreiches Testing aufbauen lässt. Verschiedene der folgenden Themen wie z.B. die Testautomatisierung sind vollständig von diesem Rohstoff abhängig. Wenn die falschen Testfälle gewählt werden, nützt es auch nichts, sie so raffiniert und effizient wie möglich auszuführen. Der Erfolg kann damit nicht herbeigeführt werden. Die Summe der Testfälle sind das Herzstück eines Testprozesses.

Was sind denn nun die Eigenschaften guter Testfälle?

Testfälle weisen unabhängig vom zu testenden System einige Qualitätsmerkmale auf, die allgemeine Gültigkeit haben. Diese Eigenschaften tragen alle zur Qualität eines Testfalles bei. Sie sind aber nicht als absolute Regeln zu betrachten, sondern als Leitlinien bzw. als Vision. Es ist in den verschiedenen Kontexten immer wieder notwendig, bei einzelnen Kriterien Abstriche zu machen, um das Ziel mit einem sinnvollen Aufwand zu erreichen.

  • Klare Zielsetzung: Es ist für jeden Testfall eindeutig, welche Abläufe, Eigenschaften und Konstellationen mit diesem Testfall überprüft werden. Diese Information ist so zugänglich, dass nachvollziehbar ist, warum dieser Testfall relevant und wichtig ist. Im Besonderen bei der Wartung der Testfälle und beim Entscheid, ob ein Testfall immer noch relevant ist oder ob es redundante Testfälle gibt, die eliminiert werden können, ist diese Information essentiell.
  • Messbarer Erfolg: Ein Testfall hat nur zwei mögliche Resultate: Success oder Failure. Um zu entscheiden, ob ein Testfall nun erfolgreich ausgeführt wurde oder nicht, braucht es Verifikationspunkte, die sicherstellen, dass sich das System under Test so verhält, wie es sollte. Ein Testfall ohne Verifikationspunkte kann nur aussagen, dass man “irgendwie durchgekommen ist, ohne dass das System zusammengebrochen ist”. Das ist als Aussage aber zu schwach.
  • Wiederholbarkeit: Ein Testfall, der zwei Mal unter den selben Bedingungen ausgeführt wird, muss das gleiche Resultat ergeben. Dies ist in der Theorie einleuchtend, in der Praxis aber oft nicht so leicht zu realisieren, da die Aussage “mit den selben Bedingungen” eigentlich nicht realisierbar ist. Verschiedene Umgebungsparameter spielen hier hinein: Was für andere Prozesse laufen noch auf dem System? Wie ist die aktuelle Auslastung des Netzwerks? etc. Dennoch müssen Testfälle, die häufiger diese Eigenschaft verletzen, analysiert und überdacht werden, da ansonsten eine vernünftige Nachvollziehbarkeit nicht gegeben ist und ein damit verbundener allfälliger Fehlereintrag für den Entwickler wenig hilfreich, der den Fehler beheben soll.
  • Unabhängigkeit: Jeder Testfall soll einen in sich geschlossenen Ablauf darstellen. Er soll nicht auf dem Resultat eines anderen Testfalls basieren. Die Reihenfolge der Testfälle innerhalb einer Testsuite soll keine Rolle spielen. Dieser Punkt wird oft zu schnell und leichtfertig geopfert, um damit Aufwand zu sparen, indem z.B. das Datensetup eines Testfalls nicht mehr erstellt werden muss, da ein anderer Testfall die Testdaten im entsprechenden Zustand zurücklässt. Der Preis, der dafür bezahlt werden muss, ist nicht zu unterschätzen. Fehler in einem vorangehenden Testfall können folgende Testfälle zu Fall bringen, obwohl die zu prüfende Funktionalität des nachfolgenden Testfalls eigentlich korrekt funktioniert. Ein Fehler kann andere Probleme maskieren, indem die Testsuite gar nie zu den Folgeproblemen kommt, weil schon der erste Fehler die folgenden verdeckt. Und im Weiteren ist es äusserst schwierig, diese Abhängigkeiten zwischen Testfällen zu überblicken und zu warten.Wenn es vom Setting her irgenwie möglich ist, sollte also jeder Testfall in seinem eigenen Universum arbeiten, das unabhängig von allen anderen Testfällen ist. Das heisst, dass er für sein gesamtes Setup (ev. den Programmstart, die Initialisierung des Datenzustandes und das entsprechende Aufräumen nach der Durchführung) selber verantwortlich ist. Dieser Grundsatz führt zu erheblich stabileren Testdurchläufen und zu aussagekräftigeren Resultaten.
  • Keine unnötigen Überprüfungen: Nach der Erkenntnis, dass Testfälle ohne Verifikation wenig bis nichts aussagen, folgt oft der gegenteilige Effekt, dass nach jedem Schritt alles überprüfbare auch tatsächlich verifiziert wird. Dagegen sprechen vor allem zwei Punkte: Der Aufwand bei der Testdurchführung und die Wartbarkeit. Der Aufwand bei der Testdurchführung ist offensichtlich. Wenn nach jedem Testschritt diverse Verifikationen durchgeführt werden, ergibt eine enorme Menge von Aktionen. Das kann sich z.B. bei der Automatisierung einer grossen Menge von Testfällen so stark ins Gewicht fallen, dass die Testsuite nicht mehr in der vorhandenen Zeit durchläuft. Der zweite Punkt ist über die gesamte Laufzeit eines Projekts und Systems aber meist der gewichtigere. Wenn sich am System eine Änderung ergibt, die eine bestimmte Verifikation betrifft, so müssen nicht nur die Testfälle, die auf diesen Punkt fokussieren, angepasst werden, sondern alle, die irgendwann im Lauf des Testfalls an diesem Punkt vorbeikommen, auch wenn es im entsprechenden Testfall eigentlich um etwas ganz anderes geht.

Auf dem Weg zu einem Skript…

Oct 07
2009

Seit einigen Jahren bin ich an der Hochschule für Technik in Rapperswil im Nachdiplomstudium bzw. MasterUpgrade Program bzw. Master of Advanced Studies Studiengang tätig. Ich habe dort ein Modul “Software Testing”, das ich unterrichte.

Das Highlight dieses Moduls sind die praktischen Übungen zu verschiedenen Themenbereichen (Test First im Bereich Unit Testing, Einsatz von dynamischen Mock Objekten, Systemtesting mit Fitnesse, Web Testing, Performance Testing, …) die in einer ausgeklügelten Übungsumgebung ausgeführt werden.

Das Sorgenkind dieser Vorlesungen sind die Slides bzw. das Skript dazu. Nachdem ich mich wieder einmal eingehender mit der Präsentationsthematik auseinandergesetzt habe, bin ich mit der Art, wie ich die Vorlesung gestalte und die Slides und das Handout einsetze einfach nicht mehr zufrieden. Ein Rhetorikworkshop mit Ralf Westphal und die Vertiefung in den Approach von presentation zen habe ich mich nun entschieden, Schritt für Schritt Teile aus dem Modul (im Ganzen 20 Lektionen) zu überarbeiten.

Als Resultat davon soll ein Skript entstehen, das die Inhalte in einer Form darlegt, die für sich allein stehen und z.B. als Vorbereitung für die Prüfung dienen kann. Damit erkaufe ich mir dann die Freiheit, in den Lektionen ganz neue Wege in der Wahl meiner Schwerpunkte und der Gestaltung der Slides auszuprobieren.

Die Erstellung dieses Skripts werde ich hier in diesem Blog Schritt für Schritt dokumentieren. Davon verspreche ich mir 1. dass mein Geschreibe von allem Anfang an adressatenbezogen ist und nicht im luftleeren Raum hängt und 2. dass ich durch allfällige Fragen und Rückmeldungen schon früh feststellen kann, wo die Schwachpunkte in meiner Argumentation liegen.

In diesem Sinne erlaube ich mir, diese Skript-Fragmente hier in den folgenden Posts zu publizieren. Vielen Dank für Inputs, Fragen, Anregungen!

Categories