Kolumne: Dino talks

Codeabdeckung und andere Aspekte von Komponententests
Kommentare

Komponententests (Unit Tests) zu schreiben, ist immer noch eine Form der Programmierung und hat die gleichen Ansprüche an gute Praktiken und Techniken wie sie in der Softwareprogrammierung für Produktionscode üblich sind. Allerdings ist das Schreiben von Komponententests durch eigene Muster und Charakteristika geprägt, auf die Sie ein Auge werfen sollten. Dieser Artikel stellt zwei Aspekte der Komponententests in den Mittelpunkt: Codeabdeckung und Isolierung.

Komponententests zielen in erster Linie darauf ab, dem Entwicklungsteam das Vertrauen in die Qualität des von ihm produzierten Codes zu verschaffen. Grundsätzlich sagen Komponententests dem Team, ob es ordnungsgemäß arbeitet und auf der richtigen Fährte ist. Komponententests sind kleine Programme, die das Verhalten von kleinen Einheiten des Produktionscodes testen, beispielsweise Methoden von Klassen. Werden alle Tests bestanden, können Sie davon ausgehen, dass Ihre Software gut gedeiht, gesund und robust ist. Doch wie zuverlässig sind die Ergebnisse von Komponententests? Da es sich bei Komponententests letztlich um Programme handelt, die andere Programme testen, hängt die Antwort größtenteils von der Qualität des Komponententestcodes ab. Man kann die Frage demnach so beantworten, dass die Ergebnisse von Komponententests zuverlässig sind, solange der zu testende Code relevant ist.

Relevanter Code

Wie bereits erwähnt, verifizieren Sie in einem Komponententest das Verhalten von Methoden und Klassen. Insbesondere überprüfen Sie, ob eine Methode scheitert, wenn sie ungültige Eingaben erhält, und ob sie sich erwartungsgemäß verhält, wenn gültige Daten übergeben werden. Letztendlich sind das die beiden Hauptszenarios für Komponententests. Was einen Test mehr oder weniger relevant macht, ist die Auswahl der zu testenden Methoden und der zu übergebenden Eingabewerte. Wenn Sie Szenarios für seltene Fälle testen und der Code die Tests besteht, können Sie getrost annehmen, dass Ihre Anwendung weiß, wie sie ordnungsgemäß auf Benutzereingaben zu reagieren hat. Treten im Programmfluss keine variablen Daten auf, lohnt es sich nicht, die jeweilige Methode zu testen. Eine Methode, die Daten lediglich entgegennimmt und speichert oder sie in trivialer Weise verarbeitet, rechtfertigt nicht die Kosten für das Schreiben und Ausführen eines Tests. Dagegen sollten Sie eine Methode, die einen Algorithmus mit mehreren Verzweigungen und Exit-Pfade implementiert, gründlich testen, um zu gewährleisten, dass alle möglichen Exit-Pfade auf ihren relevanten Code hin geprüft wurden.

Ein Test ist nur dann aussagekräftig, wenn er sich mit etwas befasst, was Sie testen möchten, das ist ziemlich abstrakt formuliert, aber zutreffend. So ist es zum Beispiel sinnvoll zu testen, ob ein Auto einer Kollision widersteht, während sich höchstwahrscheinlich ein Test erübrigt, ob der Wagen auch wirklich nicht anspringt, wenn der Benzintank leer ist. Der letztgenannte Test ist zwar nicht relevant, was aber nicht heißt, dass Sie derartige Tests vermeiden sollten. Wenn aber die Mehrheit der Tests nur eine geringe Relevanz hat, ist die Antwort, die Sie von den Tests über die Qualität des Codes erhalten, selbst nicht relevant.

Codeabdeckung

Die Gültigkeit einer Testreihe hängt in gewissem Umfang von der Anzahl der Komponententests und dem prozentualen Anteil des durch die Tests abgedeckten Codes ab. Andererseits gibt es bislang keinen Beweis für eine realistische Korrelation zwischen Codeabdeckungswerten und der Qualität von Software. Sicherlich spielt die Menge auch eine Rolle, doch Qualität ist der Dreh- und Angelpunkt. Normalerweise decken Tests nur eine Teilmenge der Codebasis ab, doch gibt es bislang noch keine allgemeine Übereinkunft, was unter „gutem“ Prozentanteil der Codeabdeckung zu verstehen ist. Manche sagen, 80 Prozent sind gut, andere machen sich nicht einmal die Mühe, eine entsprechende Quote anzugeben. Fest steht, dass eine vollständige Codeabdeckung nur umständlich, wenn überhaupt zu erreichen ist.

Alle Versionen von Visual Studio 2010 bringen Tools für die Codeabdeckung mit. Darüber hinaus ist Codeabdeckung ein recht generischer Begriff, der sich auf ziemlich viele unterschiedliche Berechnungskriterien wie zum Beispiel Funktions-, Anweisungs-, Entscheidungs- und Pfadabdeckung beziehen kann. Die Funktionsabdeckung misst, ob jede Funktion im Programm in bestimmten Tests ausgeführt worden ist. Die Anweisungsabdeckung betrachtet feiner abgestuft einzelne Zeilen des Quellcodes. Die Entscheidungsabdeckung misst die ausgewerteten Verzweigungen (zum Beispiel eine if-Anweisung), während die Pfadabdeckung prüft, ob jede mögliche Route durch einen bestimmten Teil des Codes ausgeführt wurde.

Jedes Kriterium bietet eine bestimmte Sicht auf den Code, doch was Sie zurückerhalten, sind nackte Zahlen, die Sie interpretieren müssen. Es scheint also, dass das Testen sämtlicher Codezeilen (das heißt eine hunderprozentige Anweisungsabdeckung) eine großartige Sache ist, allerdings ist ein höherer Wert für die Pfadabdeckung möglicherweise wünschenswerter. Sicherlich ist Codeabdeckung nützlich, weil sie hilft, Code aufzuspüren, der bislang von keinem Test berücksichtigt wurde. Codeabdeckung allein sagt jedoch nicht viel darüber aus, wie gut die Tests den Code untersucht haben. Stellen Sie sich zum Beispiel eine Methode vor, die eine Ganzzahl verarbeitet. Für diese Methode lässt sich durchaus eine hundertprozentige Anweisungsabdeckung erreichen, doch wenn Sie keinen Test vorsehen, in dem Sie der Methode einen ungültigen Wert außerhalb des definierten Bereichs übergeben, ernten Sie zur Laufzeit eine Ausnahme, trotz aller erfolgreichen Tests, die Sie ausgeführt haben.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -