TVSS – Code Coverage – Abgabedokument

Werbung
Testen von Software Systemen
30.03.2013
R E P O RT
Testsystem:
Getestet wird ein Binaerer Suchbaum. Das Projekt besteht aus 2 Klassen und einem Interface:
BinarySearchTree:
Interface fuer den Suchbaum, enthaelt Java Doc
MyBinarySearchTree:
Implementierung des Interafaces
BinaryTreeNode:
Knoten des Binaeren Suchbaums.
Wir haben uns fuer folgendes Beispiel entschieden, da die verschiedenen Operationen auf den
Baum ein gut geeignetes Beispiel fuer Testen / Coverage zur Verfuegung stellt. Vor allem bei
Operationen wie Remove gibt es viele Corner-Cases die getestet werden muessen.
Tool:
Wir haben uns fuer folgendes Coverage Tool entschieden:
http://www.eclemma.org/
ECLEMMA hat den Vorteil, dass es einfach in Eclipse zu integrieren ist, und die Bedienung so
einfach und selbsterklaerend ist, dass es keinerlei Einarbeitungszeit bedarf.
Binary Search Trees:
Folgendes Kapitel enthaelt die theoretischen Grundlagen, die bei der Implementierung / Testen
von Binary Search Trees wichtig sind. Anhand deren wurden die Testfaelle entworfen.
Eine Beschreibung der verwendetetn Teststrategie folgt im darauffolgenden Kapitel.
- Schlüssel, die in Knoten des linken Subbaumes eines Knoten v gespeichert sind, sind kleiner oder
gleich dem in v gespeicherten Schlüssel
- Schlüssel, die in Knoten des rechten Subbaumes eines Knoten v gespeichert sind, sind größer als
der in v gespeicherte Schlüssel
- jeder Knoten hat 0, 1 oder 2 Nachfolger
Einfuegen:
- Groessere Elemente rechts einfuegen
- Elemente kleiner/gleich links einfuegen
Entfernen:
Es muessen 3 Faelle unterschieden werden:
Fall 1: Knoten hat keinen Nachfolger Knoten kann einfach entfernt werden
Fall 2: Knoten hat nur einen Nachfolger
Knoten entfernen, und Nachfolgeknoten an dessen Stelle verschieben
Fall 3: Knoten hat zwei Nachfolger weitere Unterscheidung in 2 Fälle ...
Fall 3.1: Knoten hat keinen Nachfolger
1. Knoten suchen
2. Elternknoten merken
3. Vgl. ob zu löschender Knoten größer / kleiner als Elternknoten
4. linkes / rechtes Kind des Elternknoten wird null
Fall 3.2: Knoten hat nur einen Nachfolger
1. Knoten suchen
2. Elternknoten merken, um zu wissen ob entfernter Knoten linker oder rechter Kindknoten war
3. Knoten entfernen und und Nachfolgerknoten an dessen Stelle verschieben
Fall 3.3 Knoten hat zwei Nachfolger
Fall 3.3 a
1. einer der beiden Kindknoten hat keine Nachfolger, oder
2. linkes Kind hat keinen rechten Nachfolger, oder
3. rechtes Kind hat keinen linken Nachfolger
4. Knoten durch dieses Kind ersetzen
Fall 3.3 b
1. Knoten hat 2 Kinder, keine Einschränkungen
1) SuchendessymmetrischenNachfolgers
a) rechts-links-links-links-...-null
b) der symm. Nachfolger hat zumindest einen null-Zeiger (links)
2) Nachfolgerentfernen
Nachfolgers
a) Linkszeiger des Elternknotens des symm. Nachfolgers zeigt auf rechtes Kind des
3) Zu löschenden Knoten durch Nachfolger ersetzen
4) Eltern-Kind Relation wiederherstellen
Es wurden Testfaelle konstruiert, die alle diese theoretisch bekannten Faelle abdecken!
Testfaelle und Teststrategie:
Zum Testen der Datenstruktur braucht es zuerst eine Test-Klasse BinarySearchTreeTester
Diese Testklasse enthaelt 3 Algorithmen: Baum durchlaufen und in Array speichern
- in order
- pre order
- post order
Algorithmen hierfuer wurden aus den Buechern von Donald Knuth entnommen. Daher kann man
davon ausgehen, dass diese Algorithmen 100% korrekt sind, zumal diese auch oftmals theoretisch
bewiesen worden sind.
Diese Algorithmen werden verwendet, um den Inhalt des Baumes zu validieren.
Des weiteren kann durch das theoretische Wissen wie ein Baum aufgebaut werden muss - und
welche Auswirkunen die Operationen auf den Baum haben immer ueberprueft werden, ob der Baum
korrekt ist.
Getestet werden die Methoden welche das Interface BinarySearchTree vorgibt.
Diese Methoden wurden in 2 verschiedene Klassen unterteilt:
Klasse STATIC:
werden.
muss vor und nach jeder Operation auf den Baum ueberprueft
Dazu zaehlen die Methoden size(); toArrayPreorder; toArrayPostOrder; toArrayInOrder.
Unsere Test-Basis Klasse hat eine Methode checkStatic welche genau diese Ueberpruefung
vornimmt und in jedem Testfall mehrmals ausgefuehrt wird.
Klasse SPECIAL: fuer alle anderen Methoden wurde eine eigene Klasse mit Unit-Tests
implementiert.
Diese Klassen haben setup-Methoden welche dazu dienen einen Tree aufzubauen, auf welchem
die eigentlichen Methoden im Anschluss getestet werden.
Alle Test-Klassen leiten von TreeTest ab (TreeTest enthaelt eine Methode die alle STATIC
Methoden testet).
FindTest:
abdecken.
testet die find Methode, Testfaelle sollen 100% des Codes in der Methode find
GetParentTest:
testet die getParent Methode, Testfaelle sollen 100% des Codes in der
Methode getParent abdecken.
InsertTest:
insert abdecken.
testet die insert Methode, Testfaelle sollen 100% des Codes in der Methode
InternalExternalTest:
testet die isInternal / isExternal Methoden, Testfaelle sollen 100% des
Codes in der Methoden abdecken.
IsRootTest:
isRoot abdecken.
testet die isRoot Methode, Testfaelle sollen 100% des Codes in der Methode
RemoveTest:
testet die remove Methode, Testfaelle sollen 100% des Codes in der Methode
remove abdecken. Dies war die Aufwendigste Klasse. Es war noetig viele verschiedene Test faelle zu
erstellen. Hierfuer wurden speziell fuer denen Fall des Removes Baeume erstellt und getestet.
Es ist zu beachten, dass in jedem UnitTest dieser Klassen auch immer die STATIC tests
durchgefuehrt werden.
Alle anderen Methoden wurden durch die STATIC Test abgedeckt.
Alle Hilfsmethoden der Klasse MyBinarySearchTree wurden auch beinahe * zu 100% getestet.
* Beobachtung:
Unser Code enthaelt eine private Hilfsmethode findPrevNode.
Coverage meldet hier, dass Pfade nicht zu 100% abgedeckt wurden (in diesem Falle n == null).
Bei der Analyse des Codes haben wir festgestellt, dass n NIEMALS null sein kann. Die Aufrufe von
findPrevNode erlauben schlichtweg nicht, hier fuer n einen Null Wert zu bekommen.
Im Prinzip handelt es sich bei diesem n != null um DeadCode.
Das kann natuerlich nicht von Test-Faellen abgedeckt werden.
Daher ist das voellig in Ordnung hier keine 100%ige Abdeckung zu haben.
Die Testfaelle haben diesen Dead-Code gefunden und man kann ueberlegen beim naechsten
Refactoring diesen Dead Code zu entfernen.
Ergebnis:
Unsere Testfaelle decken die zu Testenden Klassen BinaryTreeNode zu 100% bzw
MyBinarySearchTree zu 99.9% ab.
Coverage zeigt bei MyBinarySearchTree eine Abdeckung von 97.2% an. Die fehlenden Prozent
erklaeren sich wie folgt:
Im Class file der Klasse MyBinarySearchTree sind “versteckte” Methoden die Javac einfuegt um
Generics zu unterstuetzen. Diese Methoden beinhalten teils Exception Pfade die normalerweise nicht
durchlaufen werden (man muss Absichtlich versuchen Java zum Absturz zu bringen um diese Faelle zu
testen).
Diese Methoden koennen mit dem Befehl javac -v MyBinarySearchTree.class eingesehen werden.
Coverage erkennt nicht, dass diese Methoden eigentlich nicht Teil der Implementierung sind.
Diese Pfade sollten unserer Meinung nach nicht in der Evaluierung aufscheinen.
Weiters enthaelt die Coverage Auswertung die Testfaelle selbst.
Auch hier ist Coverage nicht ganz perfekt - denn das ist nicht Teil der gewuenschten Analyse.
So scheinen zum Beispiel Testfaelle, wo man Fehlerverhalten (zB insert ( null ) ) testet auf und
beeinflussen so das Ergebnis:
Im Grossen und Ganzen ist Coverage jedoch ein sehr gutes und einfaches Tool um die
Abdeckung durch Testfaelle zu evaluieren.
Auch wenn es Teilweise ein tiefgreifendes Verstaendnis von Java benoetigt um die Ergebnisse
richtig deuten zu koennen (--> Generic Methoden)
Herunterladen