Westfälische Wilhelms-Universität Münster Ausarbeitung Qualitätssicherung von Software mit Testwerkzeugen im Rahmen des Seminars „Qualitätsmanagement in der Softwaretechnik“ Elke Schmitt Themensteller: Prof. Dr. Herbert Kuchen Betreuer: Roger Müller Institut für Wirtschaftsinformatik Praktische Informatik in der Wirtschaft Inhaltsverzeichnis 1 Was bringt Werkzeug-Unterstützung beim Testen von Software? ........................... 1 2 Klassifikation von Testwerkzeugen........................................................................... 2 3 Rational Testwerkzeuge............................................................................................. 4 4 3.1 Übersicht über die Programmpakete................................................................. 4 3.2 Die Rational Team Unifying Platform.............................................................. 4 3.3 Rational Functional Tester for Java and Web................................................... 6 3.4 Rational PurifyPlus ........................................................................................... 7 Parasoft Jtest ............................................................................................................ 10 4.1 Übersicht über die Funktionen und Integrationsmöglichkeiten...................... 10 4.2 Unit-Tests mit JTest........................................................................................ 11 4.2.1 4.2.2 4.2.3 5 Blackbox-Test............................................................................................. 12 Whitebox-Test ............................................................................................ 14 Regressions-Test......................................................................................... 15 Bewertung der Werkzeuge ...................................................................................... 16 Anhang A........................................................................................................................ 18 Anhang B ........................................................................................................................ 19 Anhang C ........................................................................................................................ 20 Anhang D........................................................................................................................ 21 Literaturverzeichnis ........................................................................................................ 23 II Kapitel 1: Was bringt Werkzeug-Unterstützung beim Testen von Software? 1 Was bringt Werkzeug-Unterstützung beim Testen von Software? Die erste Frage, die zum Thema Werkzeug-Unterstützung beim Testen von Software gestellt werden muss, ist: Warum sollte man Tests softwaregestützt durchführen? Es gibt schließlich die Möglichkeit, jedes Testproblem manuell anzugehen, ohne die Unterstützung durch Software. Dieses manuelle Vorgehen erspart dem Team die Anschaffung teurer Software und die Einarbeitung in die neuen Programme und Techniken. Das Argument für die Automatisierung von Softwaretest ist einfach. Beizer [Be95] sagt zu dieser Frage: „The argument to use is simple: Manual Testing doesn’t work. “. Die Gründe hierfür sind vielfältig und liegen einerseits in der großen Komplexität von Programmen und den entsprechend komplexen Tests, andererseits in der Ineffizienz und Unzuverlässigkeit von manuellem Testen aufgrund nicht möglicher Wiederverwendung der einmal durchgeführten Tests. Jede Wiederholung eines manuellen Tests führt zu neuen Fehlerquellen, da Menschen jedes Mal andere Fehler bei der Durchführung von Tests machen können. Besonders häufige Wiederholungen derselben Tests führen zu Langeweile und Konzentrationsverlust, was den Effekt noch verstärkt. Da Softwareentwicklung ein iterativer Prozess ist, können die einmal mit Software entwickelten Tests wiederholt angewendet werden; das erspart viel Arbeit und sorgt für eine höhere Abdeckung des neuen Programms durch Tests. Bei jeder Veränderung am Programmcode kann auf die vorhandenen Testfälle zurückgegriffen werden, um neu entstandene Probleme aufzudecken oder die Korrektheit des Programms zu bestätigen. Ein weiterer entscheidender Grund für die werkzeuggestützte Durchführung von Tests ist die Belegbarkeit der Ergebnisse. Über die Protokolldateien und generierten Berichte kann der Kunde oder eine interne Controlling-Instanz über die korrekte Ausführung der Tests informiert werden. Ein Vergleich der Kosten zwischen manuellen und automatisierten Tests kann nur schwer vorgenommen werden. Manuelles Testen kostet in jedem Projekt und jedem Entwicklungsschritt erneut Geld und Zeit. Viele Kosten entstehen beim manuellen Testen erst in späteren Stadien der Softwareentwicklung, z. B. in der Testphase beim Kunden, sind jedoch auf die mangelnde Zuverlässigkeit der Testmethode 1 Kapitel 2: Klassifikation von Testwerkzeugen zurückzuführen. Die Kosten der automatisierten Tests sind zu Beginn höher, da Programme und Hardware angeschafft und die Test-Teams geschult werden müssen. Diese Kosten fallen jedoch nur einmal für viele Projekte an, außerdem verhindern die Investitionen weitere Kosten in den späteren Phasen der Entwicklung. In dieser Ausarbeitung werden Werkzeuge zur Unterstützung und Durchführung von Tests der Firmen Rational (Teil von IBM) und Parasoft vorgestellt und verglichen. Hierzu wird in Kapitel 2 zunächst ein Vorschlag zur Einteilung der Testwerkzeuge nach ihren Funktionen gemacht und die in Kapitel 3 und 4 vorgestellten Werkzeuge in dieses Schema eingeordnet. Kapitel 3 gibt eine Übersicht über die Produktpalette von Rational im Bereich der Testwerkzeuge und stellt einige der Programme anhand von Beispielen vor. Das Produkt von Parasoft, JTest, wird in Kapitel 4 ebenso anhand von Beispielen vorgestellt. In Kapitel 5 folgen der Vergleich der Werkzeuge der beiden Firmen und ein Vorschlag für die Verwendung in der Softwareentwicklung. 2 Klassifikation von Testwerkzeugen Je nach Testart gibt es verschiedene Werkzeuge, welche die Arbeit unterstützen können. In [Li02] wird eine Gliederung nach Typen der Testwerkzeuge vorgeschlagen: • Dynamische Testwerkzeuge o Strukturorientierte Testwerkzeuge o Funktionsorientierte Testwerkzeuge o Regressionswerkzeuge o Leistungs- und Stresstestwerkzeuge • Statische Testwerkzeuge o Messwerkzeuge o Stil-Analysatoren o Werkzeuge zur Erzeugung von Grafiken und Tabellen o Slicing-Werkzeuge o Datenflussanomalieanalyse-Werkzeuge 2 Kapitel 2: Klassifikation von Testwerkzeugen • Formale Verifikationswerkzeuge • Modellierende und analysierende Werkzeuge Die am Markt erhältlichen Programme und Programmpakete decken häufig mehrere Bereiche ab und kombinieren die Ergebnisse zu einer umfassenden Ergebnishistorie. Die in dieser Arbeit vorgestellten Werkzeuge ordnen sich wie in Tab. 2.1 dargestellt in die Gliederung ein. In der Tabelle wurden die beiden letzten Punkte der Aufzählung weggelassen, da sie nicht von den Programmen abgedeckt werden. Neu hinzugekommen ist die Gruppe der Werkzeuge zur Organisation und Planung von Tests im Team. Rational Team Unifying Platform Functional Tester for Java and Web Dynamische Testwerkzeuge Strukturorientierte Testwerkzeuge Purify Plus JTest X X Funktionsorientierte Testwerkzeuge X X Regressionswerkzeuge X X Leistungs- und Stresstestwerkzeuge Statische Testwerkzeuge Parasoft X Messwerkzeuge X Stil-Analysatoren X Werkzeuge zur Erzeugung von Grafiken und Tabellen X Slicing-Werkzeuge X DatenflussanomalieanalyseWerkzeuge Werkzeuge zur Planung und Organisation der Zusammenarbeit im Team X Tab. 2.1 Funktionsübersicht der Testwerkzeuge Die genaue Erklärung der einzelnen Funktionen erfolgt in den Kapiteln zu den Testwerkzeugen, die Programme wurden hier nur nach ihren Hauptfunktionen eingegliedert. 3 Kapitel 3: Rational Testwerkzeuge 3 Rational Testwerkzeuge 3.1 Übersicht über die Programmpakete Rational bietet eine große Anzahl an Produkten zum Testen von Software an. Die Produkte werden in verschiedenen Paketen angeboten und arbeiten teilweise ineinander greifend. Rational teilt die Produkte in zwei Gruppen ein, die Rational System Testing Family sowie das Developer Testing [Ra04]. Die Rational System Testing Family besteht aus verschiedenen Modulen, die über den Rational TestManager gesteuert und integriert werden. Das zentrale Produktpaket stellt die Rational Team Unifying Platform dar. Es enthält neben dem TestManager zur Kontrolle und Steuerung von manuellen und automatisierten Tests sechs weitere Module: Unified Process, RequisitePro, ClearCase LT, ClearQuest, ProjectConsole und SoDA. Wahlweise können zusätzlich die selbständigen Module und Pakete Rational Robot, Rational Functional Tester for Java and Web und Rational Performance Tester erworben und integriert werden. Der Bereich Developer Testing beinhaltet die Entwicklungsumgebung IBM Rational Rose XDE Developer Plus, in der bereits einige Testfunktionen integriert sind. Rational Testing RealTime ist für Laufzeittests von plattformübergreifenden und eingebetteten Systemen geeignet. Ebenfalls verschiedene Laufzeittests bietet Rational PurifyPlus, wobei das Angebot an Tests größer ist als bei RealTime, dafür aber auf bestimmte Programmiersprachen und Plattformen beschränkt. Im folgenden Abschnitt werden einige Module vorgestellt und teilweise anhand eines Beispiels näher erläutert. 3.2 Die Rational Team Unifying Platform Das Programmpaket Rational Team Unifying Platform besteht aus einer Reihe von Werkzeugen, die auf die Organisation des Programmentwicklungs- und Testprozesses abzielen und neben der Zusammenarbeit untereinander auch mit verschiedenen weiteren Werkzeugen von Rational integrieren. 4 Kapitel 3: Rational Testwerkzeuge Abb. 3.1 Module der Rational Team Unifying Platform Das Konzept der Software-Entwicklung mit Produkten von Rational basiert auf dem Rational Unified Process, einem Vorgehensmodell, das laut Rational momentan zu einem de facto Industriestandard wird. Das gleichnamige Modul der Team Unifying Platform bietet eine Wissensbasis, die Softwareentwickler und Tester durch den Entwicklungsprozess führt. Rational RequisitePro ermöglicht die Verwaltung von Anforderungen. Es basiert auf Word-Dokumenten, die mit einer Anforderungsdatenbank verknüpft sind und stellt die Daten auch anderen Modulen der Rational System Testing Family zur Verfügung. Für das Change-Management und die Verfolgung von Fehlern bietet Rational ClearQuest eine flexible Grundlage. Es bietet individuell gestaltbare Formulare zur Meldung von Fehlern und Change-Requests, die den jeweiligen Entwicklern so regelmäßig und einheitlich gemeldet werden. Rational ClearQuest arbeitet eng mit dem Versionskontrollwerkzeug Rational ClearCase LT zusammen. Dieses verwaltet für die verschiedenen Dokumente und Programmteile wie Dokumentation, Modelle und Testläufe die Versionsnummern und verknüpft diese mit den Fehlermeldungen und Change-Requests aus ClearQuest. Als Schnittstelle zu Management und Kunden dient die Rational ProjectConsole. Sie generiert aus den Modulen der Rational Suite sowie aus Programmen von anderen Anbietern Berichte, die den Projektstatus zusammengefasst darstellen. Die Darstellung erfolgt als Website. Um die Informationen nutzen zu können, muss entweder eine 5 Kapitel 3: Rational Testwerkzeuge Lizenz der ProjectConsole oder eine einzeln erhältliche ProjectConsole Client Lizenz vorhanden sein. Das Kernstück aller Aktivitäten des Testens bildet der Rational TestManager. Er ist nicht nur Bestandteil der Team Unifying Platform, sondern wird auch bei den drei anderen Modulen der System Testing Family mitgeliefert. Mit diesem Tool werden manuelle Tests, Funktionstests, Regressionstests, Performancetests und Laufzeittests überwacht und gesteuert. Gefundene Fehler können an ClearQuest gemeldet und in Reporten zusammengefasst werden. Zur Dokumentation dient das Modul Rational SoDA, das die Erzeugung und Verteilung von verschiedenen Arten der Projektdokumentation unterstützt. 3.3 Rational Functional Tester for Java and Web Abb. 3.2 Module des Rational Functional Tester for Java and Web Der Functional Tester for Java and Web ist ein Programmpaket aus dem TestManager, der im Abschnitt 3.2 kurz vorgestellt wurde, und dem XDE Tester, der in früheren Versionen RobotJ hieß. Getestet werden können Programme der Techniken J2EE, J2SE, HTML, DHTML, XML, JavaScript und Java Applets. Die Funktionstests lassen sich für Regressionstests wieder verwenden. Diese Wiederverwendung wird durch die Technik ScriptAssure™ vereinfacht, welche Komponenten von Programmen, beispielsweise Buttons, auch nach Umbenennung wieder erkennt. Der XDE Tester kann in den XDE Developer oder WebSphere integriert werden und bringt eine eigene Eclipse Version als Oberfläche mit. Die Erzeugung von Test erfolgt mittels einer Java-API, die ähnlich der API von JUnit aufgebaut ist und den Ablauf von Tests in Java-Klassen festhält. Diese Klassen können entweder von Hand geschrieben werden oder mittels eines Rekorders automatisch erzeugt werden. Getestet wird zur Laufzeit, eine Analyse des Codes erfolgt nicht. Ein einfaches Beispiel für eine Testklasse ist im Folgenden dargestellt: 6 Kapitel 3: Rational Testwerkzeuge import import import import import import resources.ButtonTestHelper; com.rational.test.ft.*; com.rational.test.ft.object.interfaces.*; com.rational.test.ft.script.*; com.rational.test.ft.value.*; com.rational.test.ft.vp.*; /** * @author Elke Schmitt */ public class ButtonTest extends ButtonTestHelper { /** * Script Name : <b>ButtonTest</b> * Generated : <b>31.03.2004 15:17:29</b> * Description : XDE Tester Script * Original Host : WinNT Version 5.1 (Service Pack 1) * * @since 2004/03/31 * @author Elke Schmitt */ public void testMain (Object[] args) { startApp("DisplayMessage"); //zu testendes Programm aufrufen // Frame: Message Yes().click(); No().click(); Yes().click(); Message().close(); //Button betätigen //Button betätigen //Button betätigen //Programm schließen } } Das getestete Programm findet sich in Anhang B, es besteht aus einem Fenster sowie zwei Buttons mit den Titeln „Yes“ und „No“, die beim Anklicken eine Ausgabe im Konsolenfenster erzeugen. Die Testklasse startet das Programm, führt drei Mausklicks aus und schließt das Programm wieder. Sie wurde mit dem Rekorder erzeugt. 3.4 Rational PurifyPlus 7 Kapitel 3: Rational Testwerkzeuge Abb. 3.3 Module von Rational PurifyPlus Rational PurifyPlus ist ein Programmpaket, das drei Komponenten enthält: • PureCoverage überwacht die genutzten und damit getesteten Teile des Programmcodes und arbeitet mit Purify und Quantify zusammen. • Purify überwacht für C, C++ und Java den Speicherverbrauch für alle Methoden und hilft bei der Entdeckung von Memory Leaks. • Quantify bietet Möglichkeiten zur Identifikation von Bottlenecks in der Performance von C, C++ und Java Programmen. Es überwacht die ausgeführten Programme und berichtet die Lauf- und Wartezeiten der einzelnen Threads sowie deren Ursachen, wie z. B. das Warten auf Benutzereingaben, Freigabe von Objekten und vom Programmcode geforderte Pausen. Als Beispiel für die Vorgehensweise der Programme dient das kurze Java-Programm aus Anhang A. Zunächst wird das Programm in PureCoverage aufgerufen, um die Vollständigkeit der durchgeführten Tests zu überprüfen. Das Beispielprogramm in der vorliegenden Form durchläuft nur 85,71% des Codes, die Methode „print“ wird nicht aufgerufen und damit in den folgenden Tests auch nicht berücksichtigt. Für einen vollständigen Test müsste also die Main-Methode um den Aufruf der Methode „print“ erweitert werden, um jede Zeile des Codes zumindest einmal zu durchlaufen. Abb. 3.4 PureCoverage – Übersicht der Methoden 8 Kapitel 3: Rational Testwerkzeuge Um die nicht ausgeführten Teile des Codes zu finden, bietet PureCoverage die Ansicht des Programmcodes, ausgeführte Teile werden blau dargestellt, übersprungene Teile rot. Der nächste Schritt ist der Aufruf in Purify. Da unter Java die Speicherallokation automatisch geschieht, werden keine Zugriffsfehler auf den Speicher festgestellt. Häufig unterschätzt werden Memory Leaks in Java, die auf zwei Arten entstehen können. Durch Objektreferenzen, die nicht länger benötigt werden, kann der Garbage Collector die zugewiesenen Speicherbereiche nicht freigeben. Dies kann z. B. passieren, wenn Objekte in Arrays referenziert, und diese Arrays dann vergessen werden. Ein Memory Leak kann auch entstehen, wenn ein Javaprogramm Speicher außerhalb der Java Instanzen nutzt. Dies passiert z. B. bei der Nutzung des AWT, wo Fensterdarstellungen im Systemspeicher abgelegt werden. Purify unterstützt die Minimierung solcher Memory Leaks durch die Möglichkeit, Schnappschüsse während der Programmausführung zu machen und zu vergleichen. So können die Methoden identifiziert werden, die für die Verschwendung von Speicherplatz verantwortlich sind. Ausführliche Informationen zu diesem Thema finden sich in [Ra02] auf den Seiten 26 ff. In Abb. 3.5 ist die Speicherzuweisung eines Schnappschusses abgebildet. Abb. 3.5 Purify Übersicht der Methoden Für jede Methode kann ein ausführlicher Bericht angezeigt werden, der neben anderen Informationen die einzelnen Objekte und ihren Speicherverbrauch enthält. 9 Kapitel 4: Parasoft Jtest Zur Aufdeckung von Performance Bottlenecks wird das Programm schließlich in Quantify gestartet. Der Bericht zeigt für jede Methode die verbrauchte Zeit und für jeden Thread die Lauf- und Wartezeiten mit dem Grund für die Wartezeit. Mit Hilfe dieser Informationen kann der Programmierer die Schwachstellen identifizieren und wenn möglich beheben. Neben den Auslösern für lange Programmlaufzeiten lassen sich durch Wiederholung dieser Tests auch diejenigen Faktoren bestimmen, die für starke Schwankungen der Laufzeit sorgen, beispielsweise bei zufälliger Reihenfolge von Threads, die sich im schlechtesten Fall gegenseitig blockieren und im günstigsten Fall genau nacheinander Systemressourcen beanspruchen. Diese Zufälligkeit kann dann behoben werden um die Laufzeit des Programms zu stabilisieren und zu verkürzen. Abb. 3.6 Quantify - Übersicht der Threads 4 Parasoft Jtest 4.1 Übersicht über die Funktionen und Integrationsmöglichkeiten Anders als bei dem Produktspektrum von Rational gibt es von Parasoft für die Durchführung von Tests ein Programm, das neben Unit-Tests in den Typen Blackbox-, Whitebox- und Regressionstests auch die Einhaltung von Coding Standards unterstützt. Jtest läuft sowohl unabhängig von weiterer Software, als auch integriert in gängige Entwicklungsumgebungen wie Eclipse, JBuilder und SunForte. 10 Kapitel 4: Parasoft Jtest Abb. 4.1 Oberfläche von JTest JTest ermöglicht neben Standard-Javacode auch das Testen von Java Servlet Pages (JSP). Zu diesem Zweck werden benötigte Test-Stubs automatisch generiert. Auch für Klassen, die Benutzereingaben erwarten, generiert JTest entsprechende Stubs, die Eingaben erzeugen. Aus den Testergebnissen erstellt JTest automatisiert Berichte im HTML-Format. Die Erstellung eigener Berichtstypen unterstützt JTest durch die Erzeugung einer XMLDatei mit den Testergebnissen, deren Inhalt mit XSL oder ähnlichen Techniken in eigene Dokumente integriert werden kann. 4.2 Unit-Tests mit JTest Bei Unit-Tests wird die kleinste mögliche Einheit des Programms getestet, im Falle von Java also die Klasse, sobald sie kompiliert wurde. So wird es den Programmierern ermöglicht, so früh wie möglich Fehler zu finden und zu eliminieren. Dies spart beim späteren Testen viel Arbeit und aufwändige Fehlersuche, da die Quellen der Fehler zum Zeitpunkt der Unit-Tests noch eng einzugrenzen sind. JTest unterstützt Unit-Tests auf verschiedene Arten, die in den folgenden Unterkapiteln vorgestellt werden. Näheres zu Unit-Tests findet sich in [Pa02]. 11 Kapitel 4: Parasoft Jtest 4.2.1 Blackbox-Test Es gibt vier Möglichkeiten, Blackbox-Tests für JTest zu erzeugen. Die erste Möglichkeit nutzt des Parasoft Produkt „Design by Contract“. Es dient der Festlegung von Zuständen, die vor oder nach Ausführung eines Programmteiles (pre oder post conditions) gelten, solchen die jederzeit während der Ausführung einer Methode gelten (assertions), sowie von Zuständen, die immer zutreffen, wenn eine Methode aufgerufen werden kann (invariants). Wenn Programmcode mit „Design by Contract“ erzeugt oder bearbeitet wurde, enthält er die entsprechenden Zustände in einem standardisierten Kommentarformat, ähnlich der Technik von Javadoc. Aus diesen Kommentaren kann JTest Blackbox-Tests erzeugen, die die Einhaltung der Zusicherungen überwachen. Weitere Möglichkeiten zur Erzeugung von Tests bestehen im Schreiben eigener Testklassen oder dem Verwenden von JUnit-Testklassen. Für statische Methoden und Instanz Methoden können einfache Eingabewerte auch direkt eingetragen werden, die Tests werden dann automatisch erzeugt. Da „Design by Contract“ nicht Bestandteil dieser Arbeit ist, werden im Folgenden lediglich die drei anderen Möglichkeiten vorgestellt. Ausführliche Informationen zu der Technik „Design by Contract“, die in der gleichnamigen Software genutzt wird, findet sich auf der Homepage der Programmiersprache Eiffel [DbC04]. Abb. 4.2 Blackbox Test mit JUnit JTest unterstützt den Tester bei der Erzeugung von JUnit-kompatiblen Testklassen, indem es das Gerüst für die Klassen automatisch generiert. Die Methoden müssen dann nur noch mit dem Testablauf gefüllt werden. Der folgende Code-Ausschnitt zeigt einen Test der Klasse Simple (siehe Anhang C), die vollständige Testklasse ist in Anhang D aufgeführt. public class SimpleTest extends TestCase{ /** * Constructs a test case for the test specified in the name argument. */ public SimpleTest (String name) { 12 Kapitel 4: Parasoft Jtest super (name); /* * This constructor should not be modified. Any initialization * code should be placed in the setUp() method instead. */ } /** * Test for constructor: 'Simple ()' */ public void testSimple () { /* Replace the default fail statement with your test code. */ fail ("Empty test case."); } /** * Test for method: 'static boolean startsWith (String, String)' */ public void testStartsWith () { /* Replace the default fail statement with your test code. */ fail ("Empty test case."); } //[…] die vollständige Klasse findet sich in Anhang D /** * Test for method: 'static int add (int, int)' */ public void testAdd () { int result = 0; result = Simple.add (5, 88); assertTrue ("The result should be 93", result == 93); } //[…] die vollständige Klasse findet sich in Anhang D } Die Methode testStartsWith zeigt, wie JTest die Testmethoden erzeugt. Die Methode fail(„Empty Test Case“) wird beim Aufruf der Testklasse automatisch einen Fehlschlag erzeugen, deren Nachricht „Empty Test Case“ den Tester auf den fehlenden Inhalt der Testmethode aufmerksam macht (siehe Abb. 4.2.). Die Methode testAdd() zeigt einen einfachen Test, der bei korrekter Funktion der Methode add() aus der zu testenden Klasse erfolgreich durchgeführt wird. Der Inhalt der Methode testAdd() ist in diesem Beispiel der einzige nicht von JTest automatisch erzeugte Code. Wenn die Testklassen bereits in JUnit-Format vorhanden sind, kann JTest diese auch importieren. Statischen Methoden können auch ohne Erzeugung von Test-Klassen Eingabewerte zugewiesen werden. Der Rückgabewert muss dann beim ersten Durchlauf als korrekt 13 Kapitel 4: Parasoft Jtest markiert werden, damit bei folgenden Tests das Ergebnis automatisch überprüft werden kann. Abb. 4.3 Direkte Zuweisung eines Eingabewertes beim Blackbox-Testen Abb. 4.5 zeigt das Ergebnis der direkten Zuweisung des Wertes 7 (ARG1 = 7) an die Methode returnStaticInt(), der Rückgabewert (ebenfalls 7) wurde als korrekt markiert. Auf die Wiedergabe der getesteten Klasse StaticInstanceExample wurde aufgrund ihrer Einfachheit verzichtet. 4.2.2 Whitebox-Test Die Whitebox-Tests von Jtest finden nicht abgefangene Runtime Exceptions. Jtest findet eine Runtime Exception bei der dynamischen Analyse der Class-Datei simple.class, deren Sourcecode sich in Anhang C befindet. Wie in Abb. 4.4 zu sehen, gibt Jtest die Art der Exception (StringIndexOutofBoundsException) sowie die Aufrufparameter des Testlaufes an. Der Benutzer kann sich jetzt den Sourcecode der Klasse ansehen und editieren, um den Fehler zu beheben. Er kann auch den Testlauf anzeigen lassen, der die Exception ausgelöst hat. Abb. 4.4 Whitebox-Test mit JTest Neben dem dynamischen Testen bietet Jtest auch statische Analysen des Codes im Hinblick auf Fehler und Nichteinhaltung von Coding Standards. 14 Kapitel 4: Parasoft Jtest Abb. 4.5 Statische Analyse mit JTest In Abb. 4.5 sind eine Reihe von Fehlern im Code der Datei simple.java (Sourcecode siehe Anhang C) aufgelistet. In Zeile 8 enthält der Code einen Tippfehler, so dass innerhalb der Fallunterscheidung ein Textlabel auftritt (case10 statt case 10). Jtest macht auf fehlende Konstruktoren, Javadoc-Kommentare und Dateiheader aufmerksam und weist auf die Verwendung von Konstanten hin, die nicht als Konstante, sondern als Zahl codiert wurden. Da Coding Standards für jedes Team und für jedes Projekt anders sind, werden die jeweils gültigen Standards in einer Properties Datei abgelegt und können so im gesamten Team verwendet werden. JTest liefert eine große Anzahl von bestehenden Standards mit, welche durch eigene Standards ergänzt werden können. 4.2.3 Regressions-Test Einmal durchgeführte Tests in JTest werden gespeichert und können nach Veränderungen am Code für jede Klasse erneut durchgeführt werden. Dies stellt sicher, dass die durchgeführten Veränderungen keine bereits korrekt arbeitenden Klassen beschädigt haben. JTest merkt sich nicht nur die als korrekt markierten Ergebnisse und nutzt sie als Referenz, sondern vergleicht automatisch die Ergebnisse vorhergehender Durchläufe und meldet jede Abweichung. 15 Kapitel 5: Bewertung der Werkzeuge Abb. 4.6 Regressionstest in JTest In Abb. 4.6 ist ein Regressionstest dargestellt, bei dem im ersten Durchlauf des automatischen Tests der Methode add() andere Rückgabewerte auftraten als beim zweiten Durchlauf (Zeilen 2 und 3). Ebenfalls verändert hat sich der manuell erzeugte Test der Methode, das als korrekt markierte Ergebnis wurde nicht erneut ausgegeben (Zeile 8). Die Veränderungen wurden durch Manipulation der Klasse Simple erreicht, deren Methode add() im zweiten Durchlauf nicht nur die beiden Eingabewerte, sondern zusätzlich den Wert auf 3 den Rückgabewert addierte. 5 Bewertung der Werkzeuge Die Produkte von Rational und JTest erfüllen im Testbetrieb verschiedene Aufgaben, ein direkter Vergleich ist nicht möglich. Es wird daher im Folgenden auf die Eignung der Programme in ihren jeweiligen Aufgabenbereichen eingegangen, die Kapitel 2 entnommen werden können. Bei JTest ist insbesondere ein Vergleich mit dem Open Source Produkt JUnit [Ju04] nötig, der die Argumente für das kommerzielle Werkzeug für Unit-Tests liefern muss. Das Produktspektrum von Rational zeichnet sich durch hohe Modularität aus, so dass je nach Größe und Art des Projektes nur die erforderlichen Programme gekauft werden müssen. Bei der Zusammenarbeit mit gängigen Entwicklungsumgebungen sind sowohl bei Rational als auch bei Parasoft die verbreiteten Umgebungen berücksichtigt. Den Bereich der statischen Analyse decken die Produkte von Rational nicht ab, er ist allerdings bereits in vielen Entwicklerumgebungen integriert. In den einzelnen Bereichen machen die Werkzeuge einen guten Eindruck, die Bedienung ist leicht zu erlernen, wenn die nötige Theorie hinter den Tests verstanden wurde. Der erfahrene Programmierer erhält vielfältige Unterstützung bei der Verbesserung der Softwarequalität. Für Programmiereinsteiger ist die Produktpalette von Rational kaum geeignet, dass die Fehlerbereinigung gute Kenntnisse der Technik voraussetzt. 16 Kapitel 5: Bewertung der Werkzeuge JTest ist nicht modular aufgebaut und arbeitet lediglich mit dem Parasoft Produkt „Design by Contract“ zusammen. Es enthält Funktionen für statische und dynamische Tests, letztere auch ohne Zugriff auf den Source Code. JTest bietet zusätzlich zum Funktionsumfang von JUnit zahlreiche Automatisierungsmöglichkeiten, es generiert einen großen Teil der offensichtlich durchzuführenden Tests ohne Benutzereingriff. Dies ermöglicht ein kontinuierliches Testen ohne großen Zeitaufwand während der Entwicklung. Die gefundenen Fehlerhinweise sind auch für Programmiereinsteiger hilfreich, eine Optimierung der Performance und des Speicherverbrauches erfordert aber weitergehende Kenntnisse in der Programmierung. Abschließend kann festgestellt werden, dass JTest sich gut für Tests eignet, die parallel zum Entwicklungsprozess vom Programmierteam selbst durchgeführt werden. Für die Rettung von Projekten, die bereits in der abschließenden Testphase sind, ist JTest ungeeignet. Die Produkte von Rational eignen sich eher für große Projekte, deren Tests eine zentrale Instanz übernimmt und die sich auch in einem späteren Stadium befinden können. Auch hier ist der Beginn des Testens so früh wie möglich ideal, aber auch bereits in Schwierigkeiten befindliche Projekte lassen sich eventuell noch retten bzw. verbessern. 17 Anhang Anhang A class Message { private String messageText; public String getMessageText() { return messageText; } public void setMessageText(String m) { messageText=m; return; } public Message(String m) { setMessageText(m); return; } public boolean equals(Message m) { return this.getMessageText().equals(m.getMessageText()); } public void print() { System.out.print(getMessageText()); return; } public void println() { System.out.println(getMessageText()); return; } public static void main(String args[]) { // Zum Test der Klasse Message standardMessage=new Message("Hello World!"); standardMessage.println(); Message javaMessage=new Message("Hello Java!"); javaMessage.println(); System.out.println(standardMessage.equals(javaMessage)); return; } } Quelle: http://www11.informatik.tu-muenchen.de/ ~brueggem/Seminare/xmlUndJavaSS2000/JavaInBeispielen/javaBeispiele.html 18 Anhang Anhang B import import import import java.awt.*; javax.swing.*; javax.swing.border.*; java.awt.event.*; // // // // AWT classes Swing components and classes Borders for Swing components Basic event handling public class DisplayMessage { public static void main(String[] args) { JLabel msgLabel = new JLabel(); // Component to display the question JButton yesButton = new JButton();// Button JButton noButton = new JButton(); // Button msgLabel.setText("Are you sure?");// The msg to display msgLabel.setBorder(new EmptyBorder(10,10,10,10)); yesButton.setText((args.length >= 1)?args[0]:"Yes"); noButton.setText((args.length >= 2)?args[1]:"No"); JFrame win = new JFrame("Message"); JPanel buttonbox = new JPanel(); // The main application window // A container for the buttons win.getContentPane().setLayout(new BorderLayout()); buttonbox.setLayout(new FlowLayout buttonbox.add(yesButton); buttonbox.add(noButton); // add yes button to the panel // add no button to the panel win.getContentPane().add(msgLabel, BorderLayout.CENTER); win.getContentPane().add(buttonbox, BorderLayout.SOUTH); yesButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println("Button 1 pressed"); } }); noButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println("Button 2 pressed"); } }); win.pack(); win.show(); } } Quelle: http://www11.informatik.tu-muenchen.de/ ~brueggem/Seminare/xmlUndJavaSS2000/JavaInBeispielen/javaBeispiele.html 19 Anhang Anhang C package examples.eval; public class Simple { public static int map (int index) { switch (index) { case 0: case10: return -1; case 2: case 20: default: return -2; } } public static boolean startsWith (String str, String match) { for (int i = 0; i < match.length (); ++i) if (str.charAt (i) != match.charAt (i)) return false; return true; } public static int add (int i1, int i2) { return i1 + i2; } } Quelle: JTest Tutorial, Bestandteil der Software 20 Anhang Anhang D package examples.eval; import junit.framework.TestCase; /** * SimpleTest is a JUnit test for class examples.eval.Simple */ public class SimpleTest extends TestCase{ /** * Constructs a test case for the test specified in the name argument. */ public SimpleTest (String name) { super (name); /* * This constructor should not be modified. Any initialization * code should be placed in the setUp() method instead. */ } /** * Test for constructor: 'Simple ()' */ public void testSimple () { /* Replace the default fail statement with your test code. */ fail ("Empty test case."); } /** * Test for method: 'static boolean startsWith (String, String)' */ public void testStartsWith () { /* Replace the default fail statement with your test code. */ fail ("Empty test case."); } /** * Test for method: 'static int add (int, int)' */ public void testAdd () { int result = 0; result = Simple.add (5, 88); assertTrue ("The result should be 93", result == 93); } /** * Test for method: 'static int map (int)' */ public void testMap () { /* Replace the default fail statement with your test code. */ fail ("Empty test case."); } 21 Anhang /////////////////// /** * Used to set up the test. This method is called by JUnit before each * of the tests are executed. */ protected void setUp () { /* Add any necessary initialization code here (e.g., open a socket). */ // _simple = new Simple (); } /** * Used to clean up after the test. This method is called by JUnit * after each of the tests has been completed. */ protected void tearDown () { /* Add any necessary cleanup code here (e.g., close a socket). */ } /* * Uncomment this variable declaration and add any necessary * initialization arguments for it in the setUp() method. */ // private Simple _simple; /** * Utility main method. This will the test cases defined in this * class. * Usage: java examples.eval.SimpleTest */ public static void main (String[] args) { /* junit.textui.TestRunner will write the test results to stdout. */ junit.textui.TestRunner.run (SimpleTest.class); /* junit.swingui.TestRunner will display the test results in JUnit's swing interface. */ // junit.swingui.TestRunner.run (SimpleTest.class); } } 22 Literaturverzeichnis [Be95] Boris Beizer: Black Box Testing - Techniques for Functional Testing of Software and Systems, John Wiley & Sons, 1995 [DbC04] Homepage von Eiffel Software: http://www.eiffel.com/ [Ju04] Homepage von JUnit: http://www.junit.org/index.htm [Li02] Peter Liggesmeyer: Software Qualität: Testen, Analysieren und Verifizieren von Software, Spektrum, Akademischer Verlag, 2002. [Pa04] Homepage von Parasoft: http://www.parasoft.com/jsp/home.jsp [Pa02] Automatic Java Software and Component Testing – Using Jtest to Automate Unit Testing and Coding Standard Enforcement, Parasoft, 2002 [Ra02] PurifyPlus – Getting Started, Rational Software Corporation, 2002 [Ra04] Homepage von Rational: http://www-306.ibm.com/software/rational/