1 Einführung
2 Überblick
3 Installation und Programmstart
4 Benutzeroberfläche und Funktionalität
5 Dateien
6 Tutorien
7 Anhang
7.1 Statische Maße
7.2 Überdeckungsmaße
7.3 Instrumentationslevel
7.4 Weitere Begriffe (Glossar)

7 Anhang

7.1 Statische Maße

Unter statische Maße subsummiert SOTA alle Maßzahlen des Projektes, die durch statische Analyse des Quellcodes durch SOTA gewonnen werden. Sie werden beim Parsen des Quellcodes ermittelt und bedürfen im Gegensatz zu den Überdeckungsmaßen keiner Ausführung des Programmes. Die Maße erlauben zum einen die Abschätzung der Komplexität des Quellcodes in Hinblick auf verschiedene Kriterien und ermöglichen damit auch eine Verbesserung der Struktur des Quellcodes. Zum anderen liefern sie eine Abschätzung des nötigen Testaufwandes bzw. der Anzahl an verschiedenen Tests für die einzelnen Kriterien.

Die statischen Maße sind direkt nach dem Laden des Projektes in der ViewMetrics für alle Strukturen des Projektes einsehbar. Für die zyklomatische und essentielle Komplexität entspricht dieser Wert bei Klassen, Dateien und dem Projekt dem Maximum der Werte ihrer untergeordneten Funktionen, für alle anderen Maße werden die Werte aufsummiert.

Anmerkungen zu den ModBI- und BI-Werten: Der gesamte Komplex Ausnahmebehandlung macht eine exakte Bestimmung von Pfaden unmöglich. Der berechnete Wert ist daher immer eine untere Grenze, d.h. die minimale Anzahl an Teilpfaden beim ModBI-Test und die minimale Anzahl an Pfaden beim BI-Test, die beim Test zu erreichen möglich ist.

7.1.1 Zyklomatische Komplexität

Die zyklomatische Komplexität einer Funktion ist anhand ihres Kontrollflussgraphen definiert, der die möglichen Pfade des Programmablaufes und alle seine Verzweigungen darstellt (vgl. View CFG). Sind e und n die Anzahl der Kanten sowie der Knoten des Kontrollflussgraphen G, so ist die zyklomatische Zahl z(G) definiert als: z(G) = e - n + 2 .
Eine Funktion ohne Verzweigungen im Programmfluss hat demnach immer eine zyklomatische Komplexität von 1, jede Verzweigung im Programmablauf, z.B. durch eine if-Anweisung, erhöht die zyklomatische Komplexität um 1.

7.1.2 Essentielle Komplexität

Die Definition der essentiellen Komplexität schließt an die der zyklomatischen Komplexität an. Wenn man von einem gegebenen Kontrollflussgraphen einer Funktion rekursiv alle primitiven Kontrollstrukturen entfernt, solange dies möglich ist, dann wird die zyklomatische Komplexität des entstandenen Graphen G' definiert als essentielle Komplexität des Graphen G: e(G) = z(G').
Dabei entsprechen die primitiven Kontrollstrukturen allen einfachen Kontrollstrukturen, die außer den break-Anweisungen bei der Switch-Anweisung keine Sprünge aufweisen. Das Vorhandensein von Sprüngen aus einer Kontrollstruktur heraus macht diese und alle sie einschließenden Strukturen nichtreduzierbar und trägt somit zur Steigerung der essentiellen Komplexität bei.

7.1.3 Lines of code (LOC)

Als eines der primitivsten Maßzahlen zum Quellcode wird hier die Anzahl der Quellcodezeilen aufgeführt, die die entsprechende Struktur umfasst. Im Gegensatz zu allen anderen Maßzahlen, die SOTA berechnet, ist LOC stark von der Quellcodestrukturierung und auch von der Art der Kommentierung abhängig und daher vorsichtig zu bewerten.

7.1.4 Anzahl der Anweisungen (#Statements)

Im Gegensatz zur Lines-of-code-Maßzahl bietet die Anzahl der Anweisungen eine objektive, von der Quellcodeformatierung unabhängige Maßzahl für den Umfang des Projektes. Hierzu werden alle ausführbaren Anweisungen für alle Strukturen aufsummiert. Der Anweisungsüberdeckungstest berechnet sich durch den Vergleich der ausgeführten Anweisungen mit der Anzahl aller Anweisungen.

7.1.5 Anzahl der Abzweigungen (#Branches)

Die Anzahl der Abzweigungen ist in SOTA funktionell als Mittel zur Berechnung der Zweigüberdeckung definiert. Während die Anzahl der Verzweigungen in einer Funktion der zyklomatischen Komplexität - 1 entspricht, wird hier die Anzahl der Abzweigungen als Summe der Ausgänge aller verzweigenden Knoten definiert. Für eine Funktion ohne Verzweigungen ist also die Anzahl der Verzweigungen null, für jede hinzugefügte if-Anweisung erhöht sich der Wert um zwei.

7.1.6 Anzahl der Modifizierten Boundary-Interior-Pfade (#ModBI)

Die Anzahl der Modifizierten Boundary-Interior-Pfade entspricht der Anzahl an Teilpfaden durch den Kontrollflussgraphen, die für die vollständige Erfüllung des Modifizierten Boundary-Interior-Pfadüberdeckungstest getestet werden müssen. Die verschiedenen Arten von Teilpfaden sind dabei nach Liggesmeyer (Software-Qualität, 2002) wie folgt definiert:

In der View CFG kann man für jede einzelne Schleife die Anzahl der für sie zu testenden Teilpfade nach dieser Definition aus der Knoteninfo (durch Doppelklick auf den entsprechenden Knoten) erfahren. Hier wird dieser Wert unter ''#ModBI'' aufgeführt. In der Knoteninfo des Funktionsknoten findet man sowohl den Wert für die gesamte Funktion, als auch die Anteile durch die Teilpfade der Schleifen sowie der Teilpfade durch die gesamte Funktion.

7.1.7 Anzahl der Boundary-Interior-Pfade (#BI)

Analog zum vorhergehenden Wert wird hier die Anzahl der ausführbaren Boundary-Interior-Pfade für jede Funktion angegeben, bzw. für Klassen, Dateien und das Projekt die Summe aller sie enthaltenen Werte. Die entsprechenden Pfade sind definiert als alle ausführbaren Pfade durch die Funktion, wobei zur Begrenzung der Pfadanzahl gilt, dass bei Vorkommen von Schleifen lediglich jene Pfade getestet werden müssen, die für jede Schleife

7.1.8 Anzahl der Anweisungen mit logischen Bedingungen (#ConditionStmts.)

Zur Berechnung der Anzahl der Anweisungen mit logischen Bedingungen werden alle Vorkommen von Anweisungen mit auswertbaren logischen Bedingungen im Quellcode aufsummiert. Explizit nicht gezählt werden Endlosschleifen (''while(true)'') und Schleifen, welche über eine Menge iterieren (''for(Item item : set)'').

7.1.9 Anzahl der logischen Atome (#Atoms)

Diese Maßzahl entspricht der Summe der auswertbaren atomaren Bedingungen aus allen logischen Bedingungen. Die logischen Atome true und false werden hierbei nicht mitgezählt, da sie nicht auswertbar in Bezug auf den Überdeckungstest für Bedingungen sind und keinen Einfluss auf den Kontrollfluss nehmen.

7.1.10 Anzahl der logischen Bedingungen (#Conditions)

Die Anzahl der logischen Bedingungen enthält die Summe aller atomaren und zusammengesetzten Bedingungen. Dieser Wert ist für die Berechnung der minimal Mehrfach-Bedingungsüberdeckung wichtig.

7.2 Überdeckungsmaße

Der eigentliche Zweck SOTAs liegt in der Bewertung von Programmtests durch die Berechung von Überdeckungsmaßen. Durch das Einfügen von Instrumentierungen wird während des Programmtests eine Logdatei mit den notwendigen Daten erstellt, die es SOTA ermöglichen, im nachhinein den Programmverlauf und die Auswertungen der Bedingungen zu rekonstruieren. Aus diesen Daten werden für die einzelnen Tests die gängigsten Überdeckungsmaßzahlen bestimmt und in der View Coverage aufgelistet.

7.2.1 Function-Entry-Exit-Coverage (FEEC)

Der Function-Entry-Exit-Coveragetest fordert für die vollständige Überdeckung, dass für jede Funktion alle Eingänge und alle Ausgänge genommen werden. Seine Erfüllung wird wie folgt berechnet:

Bei Java gibt es nur je einen Eingang für eine Funktion. Als mögliche Ausgänge wird das normale Funktionsende, falls es erreicht sein sollte, sowie alle return-Anweisungen und alle throw-Anweisungen außerhalb von try-Strukturen gezählt.

7.2.2 Anweisungsüberdeckung (C0)

Für die Anweisungsüberdeckung ist es notwendig, dass jede Anweisung im Quellcode ausgeführt wurde. Da nur für Quellcode nach Instrumentierungslevel 3 jede Anweisung bei der Ausführung in der Logdatei vermerkt wird, wird im Normalfall nach dem Programmtest die Überdeckung der Anweisungen aus den geloggten Eckdaten des Kontrollflusses propagiert.

Anmerkung: In der View CFG entsprechen nicht alle Knoten Anweisungen und nicht jede Anweisung entspricht einem Knoten. Es lässt sich deshalb nicht aus den überdeckten Knoten des Kontrollflussgraphen die C0-Überdeckung berechnen, die Grundlage bildet hier der Wert #Statements aus der View Metrics.

7.2.3 Zweigüberdeckung (C1)

Die vollständige Zweigüberdeckung wird erreicht, wenn alle Zweige des Kontrollflussgraphen überdeckt wurden. Die Berechnung der prozentualen Überdeckung wird in der Praxis unterschiedlich gehandhabt, der Einfachheit halber berechnet SOTA dies anhand der Abzweigungen (vgl. 7.1.5) wie folgt:

7.2.4 Einfache Bedingungsüberdeckung (C2)

Die einfache Bedingungsüberdeckung testet ausschließlich, ob alle logischen Atome der Bedingungen sowohl wahr als auch falsch ausgewertet wurden. Damit muss jedoch noch keine Zweigüberdeckung als Minimalziel erreicht worden sein, weswegen die einfache Bedingungsüberdeckung noch keinen großen Aussagewert besitzt. Für die Berechnung der prozentualen Überdeckung zählt SOTA alle Auswertungen der Atome und vergleicht diese mit dem Zielwert.

7.2.5 Minimal Mehrfach-Bedingungsüberdeckung (MMCC)

Als praxistaugliche Bedingungsüberdeckung, die auch die Zweigüberdeckung einschließt, hat sich die minimale Mehrfach-Bedingungsüberdeckung etabliert. Hierzu werden analog zur C2 alle Auswertungen nicht nur der logischen Atome, sondern auch der zusammengesetzten, komplexen Bedingungen betrachtet. Diese müssen während des Tests jeweils zu wahr und falsch ausgewertet werden. Die Anzahl der zu untersuchenden logischen Strukturen entspricht hier der unter 6.1.10 aufgeführten Anzahl der logischen Bedingungen.

7.2.6 Modifiziert Bedingungs-Entscheidungsüberdeckung (MCDC)

Ein noch schärferes Testkriterium liefert der modifizierte Bedingungs-Entscheidungsüberdeckungstest. Hierzu ist es nicht nur notwendig, dass alle logischen Atome einer jeden Bedingung die Werte wahr und falsch annehmen, sondern es muss auch für jedes einzelne Atom gelten, dass es Wertbelegungen für diese Bedingung gab, die sich ausschließlich in diesem Atom unterschieden und zu einer unterschiedlichen Auswertung der gesamten zusammengesetzten Bedingung führte. Damit wird sichergestellt, dass getestet wurde, dass das Ändern das Wahrheitswertes eines jeden Atoms auf die Gesamtbedingung einen Einfluss hat. Die beide Wahrheitsvektoren einer Bedingung, die diese Forderung für ein Atom erfüllen, werden MCDC-Paar genannt. Die Überdeckungsmaßzahl berechnet sich dann anhand der gefundenen MCDC-Paare wie folgt:

7.2.7 Mehrfach-Bedingungsüberdeckung (C3)

Den umfangreichsten Bedingungstest fordert der Mehrfach-Bedingungsüberdeckungstest, da er den Test aller Wahrheitsvektoren einer jeden Bedingung fordert. Der Testaufwand steigt damit jedoch exponentiell mit der Anzahl der Bedingungen an. Hinzu kommt, dass in den meisten Fällen nicht alle Kombinationen von Wahrheitswerten der Atome überhaupt belegbar sind, sondern viele rein praktisch unmöglich sind, ohne dass dies einfach zu erkennen wäre. Der Testauwand von 2^(#Atome) wird lediglich durch die Anwendung von Short-circuit-Operatoren reduziert, welche die Auswertung der Bedingungen stoppt, sobald das Ergebnis der Gesamtbedingung unumstößlich fest steht.

7.2.8 Modifizierte Boundary-Interior-Pfadüberdeckung (ModBI)

Der Modifizierte Boudary-Interior-Pfadüberdeckungstest ist ein von Liggesmeyer vorgeschlagener Test, der eine nochmalige Reduktion der nötigen Testfälle gegenüber dem Boundary-Interior-Pfadtest beinhaltet (siehe Definition in 7.2.9). Für die Berechnung der Überdeckungsmaßzahl werden für alle Pfade durch eine Funktion während des Programmtests die MBI-Pfade berechnet, die sie überdecken, und die Summe dieser überdeckten Teilpfade wird mit der Anzahl der möglichen MBI-Pfade, definiert in 7.2.9, verglichen.

Da die Anzahl der ModBI-Pfade nur ein Minimum möglicher Teilpfade nach diesem Kriterium ist, können in der Praxis mehr MBI-Pfade durchlaufen werden (z.B. durch Ausnahmen), als durch diese minimale Schranke vorgegeben wurde. In diesem Fall wird der Überdeckungswert natürlich auf 1 begrenzt.

7.2.9 Boundary-Interior-Pfadüberdeckung (BI)

Die Boundary-Interior-Pfadüberdeckung wird analog zur Modifizierten Boundary-Interior-Pfadüberdeckung berechnet, wobei lediglich für alle Pfade durch eine Funktion die BI-Pfade berechnet und deren Anzahl mit der möglichen Anzahl an möglichen BI-Pfaden verglichen wird.

7.3 Instrumentationslevel

Um dem Nutzer zu erlauben, den mitunter sehr hoch ausfallenden Speicherbedarf der Logdateien sinnvoll und variabel zu begrenzen, lässt sich der Quellcode in verschiedenen Stufen instrumentieren. Eine Konfiguration der Instrumentierung wird in einem Instrumentierungschema, kurz IScheme, zusammengefasst und für das entsprechende Projekt gesichert. Für alle Projekte gibt es die drei grundlegenden ISchemes, die der Instrumentierung nach den entsprechenden Leveln entsprechen, von SOTA vorgegeben.

Level 0

Die Zuweisung des Level 0 als Instrumentierungslevel für eine Struktur hat zur Folge, dass diese von der Instrumentierung ausgenommen wird. Dies ist z.B. sinnvoll, wenn man Funktionen, die viel Loginformationen (durch häufiges Ausführen oder komplexe Funktionsabläufe) erzeugen würden, aber schon hinreichend getestet worden sind, von weiteren Tests ausschließen möchte.

Level 1

Die grundlegendste Instrumentierung wird mit Level 1 angeboten. Hier werden der Funktionseingang, seine Ausgänge und sämtliche verzweigende Programmstrukturen so instrumentiert, dass aus diesen Informationen der Kontrollfluss durch die Funktion rekonstruiert werden kann. Mit diesen Daten ist es möglich alle Überdeckungsmaße bis auf die der Bedingungsüberdeckung zu berechnen.

Level 2

Zusätzlich zu Level 1 wird bei der Instrumentierung nach Level 2 auch die Belegung jedes Atoms, sofern es auch im Programm ausgewertet werden würde, in der Logdatei gesichert. Diese Daten ermöglichen es, zusätzlich zu den Maßen nach Level 1 auch die Bedingungsüberdeckungsmaße für den Programmtest berechnen zu lassen.

Level 3

Schließlich bietet SOTA mit der Instrumentierung nach Level 3 eine vollständige Instrumentierung des Quellcodes an. Es wir hier neben den ausgewerteten Atomen auch die Ausführung sämtlicher einzelnen Anweisungen im Logfile vermerkt, wodurch dieses im Vergleich zu den der anderen Instrumentierungslevel in einem erheblichen Maße an Umfang zunehmen kann. Diese Option der Instrumentierung wird nicht nur der Vollständigkeit halber angeboten, sie ermöglicht außerdem die detaillierte Auswertung des Kontrollflusses bei unnormal terminierenden Programmen und bei der Ausnahmebehandlung.

7.4 Weitere Begriffe (Glossar)

Ant/Ant-Buildfile

Apache Ant ist ein mit make-vergleichbares Werkzeug zum automatischen Kompilieren von Quellprojekten, welches in der Java-Entwicklung sehr verbreitet ist. Die Ziele und Anweisungen für die Kompilation stehen in einer XML-Datei, dem Ant-Buildfile, welches von ant gelesen die Kompiliation ermöglicht.

Bei der Nutzung von Eclipse besteht die Möglichkeit, sehr einfach ein ant-Buildfile über File -> Export -> Ant Buildfile zu exportieren.

ASC-Logger.ini / ASCLogger.jar

Für den Programmtest von Java-Programmen wird eine Logging-Komponente namens ASCLogger.jar benötigt, die das Projekt eingebunden werden muss und während des Testlaufes die Sicherung der Überdeckungsdaten übernimmt. Die Einbindung in Eclipse funktioniert dabei über Project -> Properties -> Java Build Path -> Add JARs bzw. Add External JARs, je nachdem, ob man die ASCLogger-Bibliothek in das Projekt eingefügt hat oder sie aus dem SOTA-Verzeichnis lädt. Die Informationen zum konkreten Testfall, d.h. Projektname,Testname, Beschreibung und das verwendete IScheme werden über eine Initialisierungsdatei namens ASCLogger.ini bereitgestellt, die beim Teststart im Ausführungsverzeichnis des Testprogrammes erstellt wird und von dort durch den ASCLogger gelesen wird.

Ausführungsverzeichnis des Testprogrammes

Das Ausführungsverzeichnis (execution directory) des Testprogrammes ist das Verzeichnis, aus welchem es gestartet wird. D.h. das Verzeichnis, wo man java -cp .. classname ausführt, bzw. bei der Verwendung eines Startskripts das diese Batch-Datei enthaltene Verzeichnis. Bei der RCP-Entwicklung unter Eclipse wird das RCP-Programm im Basisverzeichnis der Platform, d.h. von Eclipse, gestartet. In diesem Fall ist das Ausführungsverzeichnis also "..\eclipse\".

Dieses Ausführungsverzeichnis wird benötigt, um dort die ASCLogger.ini zu erstellen, welche Informationen zum Test für die Loggingkomponente enhält, und hierhin werden auch die Logdateien geschrieben.

Basisverzeichnis des Testprogrammes

Das Basisverzeichnis des Testprogrammes ist sein Wurzelverzeichnis, wo also die Quelldateien bzw. Binaries (gegebenenfalls in Unterverzeichnissen) liegen. Von hier werden die Quellen des Projektes importiert und hierhin wird der Überdeckungsreport geschrieben.

Basisverzeichnis von SOTA

Das Basisverzeichnis von SOTA ist "..\SOTA\", wo sich die ausführbare SOTA.exe und die ASCLogger.jar-Bibliothek befindet. An diesem Ort wird auch die Projektdatei <projectname>.project sowie die Logdatei von SOTA mit den Programmausschriften erstellt.

Dynamischer Programmtest

Jeder Test eines Programmes, der seine Ausführung benötigt, ist ein dynamischer Programmtest. Dazu gehören unter anderem funktionale (Black-Box-) und strukturorientierte (White- oder Glass-Box-)Tests. SOTA dient als Werkzeug für den strukturorientierten Test dazu, für diesen die neun verschiedenen Überdeckungsmaße zu ermitteln.

Instrumentationsschema / IScheme

SOTA bietet verschiedene Level der Instrumentierung an, um eine Begrenzung des Overhead durch die Instrumentierung zu ermöglichen. Ein Instrumentationsschema (kurz: IScheme) kapselt die Informationen für eine spezifische Art der Instrumentierung des Projektes, d.h. liefert eine Zuordnung aller Funktionen des Projektes auf ein Instrumentationslevel.

SOTA beinhaltet immer die drei grundlegenden ISchemes, die eine Überdeckung nach den Leveln 1, 2 und 3 ermöglichen. Wird ein neues IScheme erstellt, so werden diese Daten in der Projektdatei <projectname>.project im SOTA-Basisverzeichnis gespeichert und können in Zukunft für dieses Projekt genutzt werden.

Startskript / Batchdatei

Das Startskript (unter Windows eine Batchdatei) ist eine Datei, deren Ausführung das Starten des Testprogrammes verursacht. Es muss also lediglich den typischen Java-Aufruf "java -cp .. classname" in einer für das Projekt spezifizierten Variante enthalten. Wurde das Startskript in SOTA eingebunden, so lässt sich das Testprogramm im Manuellen Programmtest aus SOTA heraus starten.

Statische Programmanalyse

Im Gegensatz zum dynamischen Programmtest arbeitet die statische Programmanalyse ohne Ausführung des Testprogrammes, sondern lediglich mit den Informationen, die durch das Parsen des Programmes gegeben werden. SOTA ermittelt aus dem Quellcode zehn verschiedene statische Maße, die Informationen über die Struktur und Komplexität des Programmes bzw. seiner Komponenten liefern.