© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Java: Kapitel 6
Programmentwicklung in Java:
Javadoc & JUnit
Programmentwicklung WS 2008/2009
Holger Röder
holger.roeder@informatik.uni-stuttgart.de
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Überblick über Kapitel 6
Code-Dokumentation mit Javadoc
Einführung in Javadoc
Javadoc-Kommentare
Javadoc-Tags
Erstellung der HTML-Dokumentation
Unit-Tests mit dem JUnit-Framework
Unit-Tests in Java
JUnit am Beispiel
Testauswertung, Vor- und Nachbereitung von Testfällen
Ausführung von JUnit-Testfällen, Integration in Eclipse
Mock-Objekte
2
© Holger Röder
Javadoc ist ein Code-Dokumentationswerkzeug, das aus speziellen
Kommentaren im Java-Code eine API-Dokumentation im HTML-Format
erzeugt.
Javadoc wird von Sun entwickelt und ist Bestandteil der Java SE.
Die offizielle Java API-Dokumentation wird mit Javadoc erstellt.
Programmentwicklung
Winter 2008/2009
Javadoc
se
3
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Javadoc-Kommentierung
Die Informationen, die von Javadoc in die Dokumentation
aufgenommen werden sollen, müssen im Java-Quellcode als JavadocKommentare angegeben werden: /** ... */
Einzelne Parameter, Rückgabewerte etc. werden innerhalb dieser
Kommentare über Javadoc-Tags dokumentiert: @param, @return etc.
public class Personenliste {
/**
Javadoc* Liefert die Personen zurück, die am
Kommentar
* angegebenen Datum im Jahr Geburtstag haben.
*
Kommentar für jeden Parameter
* @param monat Geburtsmonat
der Methode
* @param tag
Geburtstag
* @return Liste der Geburtstagskinder; leere Liste, falls
*
keine Person an diesem Tag Geburtstag hat
Kommentar für
*/
Rückgabewert
public List<Person> getGeburtstagskinder(int monat, int tag) {
... // Implementierung
}
}
4
© Holger Röder
/**
* Liefert die Personen zurück, die am
* angegebenen Datum im Jahr Geburtstag haben.
*
* @param monat Geburtsmonat
* @param tag
Geburtstag
* @return Liste der Geburtstagskinder; leere Liste, falls
*
keine Person an diesem Tag Geburtstag hat
*/
Programmentwicklung
Winter 2008/2009
Javadoc-Kommentierung (2)
se
5
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Übersicht: Wichtige Javadoc-Tags
Javadoc-Tag
Beschreibung
@author name-text
Adds an „Author“ entry with the specified name-text to
the generated docs when the -author option is used.
@deprecated deprecated-text
Adds a comment indicating that this API should no longer
be used (even though it may continue to work).
@exception class-name
description
The @exception tag is a synonym for @throws.
@param parameter-name
description
Adds a parameter with the specified parameter-name
followed by the specified description to the "Parameters"
section.
@return description
Adds a „Returns“ section with the description text.
@see reference
Adds a „See Also“ heading with a link or text entry that
points to reference.
@since since-text
Adds a „Since“ heading with the specified since-text to
the generated documentation.
@throws classname description
Adds a „Throws“ subheading to the generated
documentation, with the class-name and description text.
@version version-text
Adds a „Version“ subheading with the specified versiontext to the generated docs when the -version option is
used.
Quelle: Sun (http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/javadoc.html)
6
© Holger Röder
Winter 2008/2009
Erstellung der HTML-Dokumentation
Manuelle Ausführung von Javadoc:
javadoc [options] [packagenames] [sourcefiles] [@files]
Einzelne Klasse: javadoc -d apidoc Personenliste.java
Paket: javadoc -d apidoc pe.doctest
Die Aufrufe erzeugen im Zielverzeichnis apidoc
die Dokumentation für die Klasse bzw. das Paket.
Programmentwicklung
In Eclipse: Über Project Æ Generate Javadoc…
se
Javadoc generiert standardmäßig verschiedene
HTML-Dateien, Stylesheets etc. im angegebenen
Zielverzeichnis.
Startseite der generierten API-Dokumentation:
index.html
7
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Javadoc – Details
Javadoc-Kommentare können mit HTML-Tags formatiert werden:
/**
* Liefert die Personen zurück, die am <strong>angegebenen Datum
* </strong> im Jahr Geburtstag haben.<br /><br />
* Aufruf-Beispiel: <code>getGeburtstagskinder(4, 11); </code>
*/
Javadoc ist nicht auf die Erzeugung von HTML-Dateien beschränkt.
Die Verarbeitung der Javadoc-Kommentare erfolgt mit Hilfe
sogenannter Doclets. Das Standard-Doclet erzeugt die APIDokumentation im HTML-Format.
Es existieren aber auch Doclets für andere Ausgabeformate (XML,
DHTML, Framemaker etc.) und Anwendungszwecke (Prüfung der
Kommentare, Testfallgenerierung etc.).
Darüber hinaus können mit individuellen Taglets auch weitere @Tags
verarbeitet werden.
8
© Holger Röder
Ludewig/Lichter, 2007: Einzeltest
Bei diesem Test werden einzelne, überschaubare
Programmeinheiten getestet, je nach verwendeter
Programmiersprache also z. B. Funktionen, Unterprogramme oder
Klassen. Er wird häufig als Unit-Test bezeichnet.
Programmentwicklung
Winter 2008/2009
Unit-Tests
se
9
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Unit-Tests in Java
Als einzelne, überschaubare Einheiten werden in der Regel Klassen
gewählt.
Für jede zu testende Klasse (class under test) wird eine eigene TestKlasse erstellt, die möglichst alle (sichtbaren) Methoden der zu
testenden Klasse testet.
Auch für alle Sonderfälle, Ausnahmefälle und Fehlerfälle einer Klasse
oder Methode werden Tests implementiert, die diese abdecken.
Die Testfälle werden innerhalb einer Testumgebung durchgeführt,
anschließend werden Soll- und Ist-Ergebnisse verglichen.
In vielen Fällen werden Unit-Test-Frameworks eingesetzt, die die
Entwicklung von Unit-Tests erleichtern, indem sie z. B. die Testtreiber
bereitstellen.
10
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
JUnit
JUnit ist ein Unit-Test-Framework für Java, das ursprünglich von Kent
Beck und Erich Gamma entwickelt wurde und mittlerweile als QuasiStandard für Unit-Tests im Java-Bereich gilt.
Motto: „Keep the bar green to keep the code clean!“
Ein farbiger Balken fasst das Ergebnis der Testausführung zusammen:
findet der Test keine Fehler, wird der Balken grün; ein roter Balken
zeigt Fehler an.
Die aktuelle Version JUnit 4 setzt die Neuerungen in Java 5, wie z. B.
Annotationen, statische Importe etc., ein (und voraus).
http://www.junit.org
11
© Holger Röder
Testcode und Anwendungscode sind getrennt. Die Testfälle werden
häufig in einer separaten Klassenhierarchie strukturiert.
Die einzelnen Testfälle sind unabhängig voneinander, können aber
auch zusammengefasst werden.
Nach der Ausführung von JUnit wird das Testergebnis sofort
angezeigt (grüner bzw. roter Balken).
JUnit ist in viele Java-IDEs integriert.
Programmentwicklung
Winter 2008/2009
Merkmale von JUnit
se
12
© Holger Röder
Winter 2008/2009
JUnit-Beispiel: Anwendungsklasse Euro
Die Anwendungsklasse Euro soll getestet werden.
Euro repräsentiert Euro-Geldbeträge als Wertobjekte.
public class Euro {
final long cents;
public Euro(double d) {
cents = Math.round(d * 100.0);
}
Programmentwicklung
public double getBetrag() {
return cents / 100.0;
}
se
public Euro addiere(Euro e) {
return new Euro(getBetrag() + e.getBetrag());
}
}
13
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
JUnit-Beispiel: Der erste Testfall
JUnit-Testfälle werden in „normalen“ Java-Klassen implementiert. Die
Kennzeichnung der Testmethoden geschieht über die Annotation @Test.
Für den Vergleich von Soll- und Ist-Resultaten existieren verschiedene
assert-Methoden, die statisch importiert werden können.
Import der JUnitAnnotation Test
import org.junit.Test;
import static org.junit.Assert.*;
Statischer Import der
JUnit-assert-Methoden
public class EuroTest {
Einzelne Testfälle werden
als public-voidMethoden implementiert
und mit @Test annotiert.
@Test public void betrag() {
Euro dreiEuro = new Euro(3.0);
assertEquals("getBetrag: ",
3.0, dreiEuro.getBetrag(), 0.001);
}
}
assertEquals vergleicht Soll- und Ist-Resultat
(der letzte Parameter gibt die Toleranz bei
Gleitkommavergleichen an)
Die Ausführung liefert den „grünen Balken“!
14
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Soll-Ist-Vergleich: assert…()-Methoden
Die Klasse org.junit.Assert bietet Vergleichsmethoden, die einzeln
oder als Gesamtheit (Assert.*) statisch importiert und in Testfällen
verwendet werden können.
Vergleich primitiver Typen, z. B.:
assertEquals(int expected, int actual)
assertEquals(double expected, double actual,
double delta)
Delta als Toleranz beim Gleitkommavergleich
Vergleich von Objekten, z. B.:
assertEquals(Object expected, Object actual)
Vergleich erfolgt über equals()-Methode
assertNotNull(Object object)
Bedingungen, z. B.:
assertTrue(boolean condition)
Alle Methoden existieren auch als Variante mit Fehlermeldung:
assertTrue(String message, boolean condition)
15
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Vor- und Nachbereitung von Testfällen
Häufig sind vor oder nach der Ausführung der Testfälle bestimmte
Vorbereitungs- oder „Aufräumarbeiten“ notwendig.
Sollen bestimmte Methoden vor oder nach jedem Testfall ausgeführt
werden, können diese mit @Before oder @After annotiert werden.
public class EuroTest {
Wird vor jeder @Test-Methode
Euro dreiEuro;
erneut ausgeführt
@Before public void vorbereitung() {
dreiEuro = new Euro(3.0);
Wichtig: Methode muss public
void und parameterlos sein!
}
@Test public void betrag() {
assertEquals(3.0, dreiEuro.getBetrag(), 0.001);
}
@Test public void addieren() {
Euro sechsEuro = dreiEuro.addiere(dreiEuro);
assertEquals(6.0, sechsEuro.getBetrag(), 0.001);
}
}
Für die einmalige Ausführung von statischen Methoden vor bzw. nach
allen Testfällen in einer Testklasse existieren die Annotationen
@BeforeClass und @AfterClass.
16
© Holger Röder
Winter 2008/2009
Erwartetete Ausnahmen
Wenn eine Ausnahme (Exception) erwartet wird, kann die erwartete
Ausnahme (bzw. ihr Class-Objekt) als Attribut expected der @TestAnnotation angegeben werden.
@Test(expected=ArithmeticException.class)
public void divisionDurchNull() {
Division durch Null: hier wird eine
int ergebnis = 3 / 0;
ArithmeticException erwartet
}
Programmentwicklung
Der Testfall ist erfolglos (grüner Balken), wenn eine Ausnahme auftritt;
tritt keine Ausnahme auf, ist der Test erfolgreich (roter Balken).
se
17
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Ausführung von JUnit-Testfällen
JUnit-Testfälle können integriert innerhalb der IDE, aber auch manuell
über die Kommandozeile ausgeführt werden.
Beispiel (Windows):
java -cp %JUNIT_HOME%\junit.jar;. org.junit.runner.JUnitCore
paket.Klasse
JUnit kann in beliebige Java-Programme eingebunden und Testfälle auf
diese Weise ausgeführt werden. Die Auswertung (und Anzeige) der
Testergebnisse muss in diesem Fall vom aufrufenden Programm
durchgeführt werden.
import org.junit.runner.JUnitCore;
Beliebige Anzahl auszuführender
import org.junit.runner.Result;
Testklassen
public class RunMyTests {
public static void main(String[] args) {
Result testResult = JUnitCore.runClasses(
EuroTest.class, NochEineTestklasse.class);
System.out.println("Fehler: " + testResult.getFailureCount());
}
}
Individuelle Auswertung
18
Eclipse unterstützt JUnit 4 von Haus aus. Die JUnit-Bibliothek kann
über die Project Properties eingebunden werden.
Programmentwicklung
Winter 2008/2009
© Holger Röder
JUnit in Eclipse: Einbindung
se
Wichtig: Version 4 von JUnit einbinden!
19
Über Run As JUnit Test können einzelne Klassen (mit JUnit-Testfällen)
oder ganze Pakete mit Testklassen als JUnit-Test ausgeführt werden
Programmentwicklung
Winter 2008/2009
© Holger Röder
JUnit in Eclipse: Ausführung
se
Beispiel: Testklasse mit insgesamt 7 Testfällen, von
denen einer (parseFehler) erfolgreich ist.
20
© Holger Röder
Winter 2008/2009
Programmentwicklung
se
Mock-Objekte
Häufig werden bei Unit-Tests Ressourcen benötigt, die bei der
Testausführung nicht zur Verfügung stehen, weil sie z. B. noch nicht
fertig sind oder die Anbindung zu aufwändig wäre. Typische Beispiele:
Datenbank, Server, andere Programmkomponenten etc.
In solchen Fällen kann es sinnvoll sein, Mock-Objekte einzusetzen.
Mock-Objekte sind Attrappen: sie implementieren die gleiche
Schnittstelle wie die „echten“ Objekte und können diese deshalb – für
den Test – ersetzen (und simulieren).
In der Java API werden Schnittstellen intensiv verwendet. Die
Voraussetzungen für Mock-Objekte sind somit häufig gegeben.
Tests können somit unabhängig von der Verfügbarkeit der „echten“
Objekte (bzw. Infrastruktur) durchgeführt werden.
http://www.mockobjects.com
21
© Holger Röder
Mock-Objekte: Beispiel
«interface»
Datenbank
Programmentwicklung
Winter 2008/2009
+holePersonen(): List<Person>
se
In der Anwendung wird nur
gegen diese Schnittstelle
implementiert
MockDatenbank
SQLDatenbank
+holePersonen(): List<Person>
+holePersonen(): List<Person>
public List<Person> holePersonen() {
List<Person> liste =
new ArrayList<Person>();
Person p1 = new Person(
"Carl Coder", 27, 4550.0);
Person p2 = new Person(
"Lisa Lind", 21, 3200.0);
liste.add(p1);
liste.add(p2);
return liste;
}
Mock-Objekt: simuliert eine
Datenbank und liefert einige
“sinnvolle” Person-Objekte
zurück
public List<Person> holePersonen() {
...
Connection c = DriverManager.getConnection(
"jdbc:derby:TestDB;create=true");
Statement s = c.createStatement();
ResultSet r = s.executeQuery(
"SELECT * FROM person");
...
}
“Echter” Datenbankzugriff (für den Test
evtl. nicht verfügbar, zu teuer o.ä.)
22