Java: Kapitel 6 Programmentwicklung in Java: Javadoc & JUnit Programmentwicklung WS 2008/2009 Holger Röder holger.roeder@informatik.uni-stuttgart.de
Ü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 Eclip Mock-Objekte 2
Javadoc 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. 3
Javadoc-Kommentierung Die Informationen, die von Javadoc in die Dokumentation aufgenommen werden sollen, müsn im Java-Quellcode als Javadoc- Kommentare angegeben werden: /**... */ Einzelne Parameter, Rückgabewerte etc. werden innerhalb dier Kommentare über Javadoc-Tags dokumentiert: @param, @return etc. Javadoc- Kommentar Kommentar für Rückgabewert public class Personenliste { /** * Liefert die Personen zurück, die am * angegebenen Datum im Jahr Geburtstag haben. * * @param monat Geburtsmonat * @param tag Geburtstag Kommentar für jeden Parameter der Methode * @return Liste der Geburtstagskinder; leere Liste, falls * keine Person an diem Tag Geburtstag hat */ public List<Person> getgeburtstagskinder(int monat, int tag) {... // Implementierung 4
Javadoc-Kommentierung (2) /** * 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 diem Tag Geburtstag hat */ 5
Übersicht: Wichtige Javadoc-Tags Javadoc-Tag @author name-text @deprecated deprecated-text @exception class-name description @param parameter-name description @return description @e reference @since since-text @throws classname description @version version-text Beschreibung Adds an Author entry with the specified name-text to the generated docs when the -author option is ud. Adds a comment indicating that this API should no longer be ud (even though it may continue to work). The @exception tag is a synonym for @throws. Adds a parameter with the specified parameter-name followed by the specified description to the "Parameters" ction. Adds a Returns ction with the description text. Adds a See Also heading with a link or text entry that points to reference. Adds a Since heading with the specified since-text to the generated documentation. Adds a Throws subheading to the generated documentation, with the class-name and description text. Adds a Version subheading with the specified versiontext to the generated docs when the -version option is ud. Quelle: Sun (http://java.sun.com/j2/1.5.0/docs/tooldocs/windows/javadoc.html) 6
Erstellung der HTML-Dokumentation Manuelle Ausführung von Javadoc: javadoc [options] [packagenames] [sourcefiles] [@files] Einzelne Klas: javadoc -d apidoc Personenliste.java Paket: javadoc -d apidoc pe.doctest Die Aufrufe erzeugen im Zielverzeichnis apidoc die Dokumentation für die Klas bzw. das Paket. In Eclip: Über Project Generate Javadoc Javadoc generiert standardmäßig verschiedene HTML-Dateien, Stylesheets etc. im angegebenen Zielverzeichnis. Startite der generierten API-Dokumentation: index.html 7
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 API- Dokumentation 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
Unit-Tests Ludewig/Lichter, 2007: Einzeltest Bei diem Test werden einzelne, überschaubare Programmeinheiten getestet, je nach verwendeter Programmiersprache also z. B. Funktionen, Unterprogramme oder Klasn. Er wird häufig als Unit-Test bezeichnet. 9
Unit-Tests in Java Als einzelne, überschaubare Einheiten werden in der Regel Klasn gewählt. Für jede zu testende Klas (class under test) wird eine eigene Test- Klas erstellt, die möglichst alle (sichtbaren) Methoden der zu testenden Klas testet. Auch für alle Sonderfälle, Ausnahmefälle und Fehlerfälle einer Klas oder Methode werden Tests implementiert, die die abdecken. Die Testfälle werden innerhalb einer Testumgebung durchgeführt, anschließend werden Soll- und Ist-Ergebnis verglichen. In vielen Fällen werden Unit-Test-Frameworks eingetzt, die die Entwicklung von Unit-Tests erleichtern, indem sie z. B. die Testtreiber bereitstellen. 10
JUnit JUnit ist ein Unit-Test-Framework für Java, das ursprünglich von Kent Beck und Erich Gamma entwickelt wurde und mittlerweile als Quasi- Standard 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 tzt die Neuerungen in Java 5, wie z. B. Annotationen, statische Importe etc., ein (und voraus). http://www.junit.org 11
Merkmale von JUnit Testcode und Anwendungscode sind getrennt. Die Testfälle werden häufig in einer paraten Klasnhierarchie 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. 12
JUnit-Beispiel: Anwendungsklas Euro Die Anwendungsklas Euro soll getestet werden. Euro repräntiert Euro-Geldbeträge als Wertobjekte. public class Euro { final long cents; public Euro(double d) { cents = Math.round(d * 100.0); public double getbetrag() { return cents / 100.0; public Euro addiere(euro e) { return new Euro(getBetrag() + e.getbetrag()); 13
JUnit-Beispiel: Der erste Testfall JUnit-Testfälle werden in normalen Java-Klasn implementiert. Die Kennzeichnung der Testmethoden geschieht über die Annotation @Test. Für den Vergleich von Soll- und Ist-Resultaten existieren verschiedene asrt-methoden, die statisch importiert werden können. Import der JUnit- Annotation Test Einzelne Testfälle werden als public-void- Methoden implementiert und mit @Test annotiert. import org.junit.test; import static org.junit.asrt.*; public class EuroTest { @Test public void betrag() { Euro dreieuro = new Euro(3.0); asrtequals("getbetrag: ", 3.0, dreieuro.getbetrag(), 0.001); asrtequals vergleicht Soll- und Ist-Resultat (der letzte Parameter gibt die Toleranz bei Gleitkommavergleichen an) Die Ausführung liefert den grünen Balken! Statischer Import der JUnit-asrt-Methoden 14
Soll-Ist-Vergleich: asrt ()-Methoden Die Klas org.junit.asrt bietet Vergleichsmethoden, die einzeln oder als Gesamtheit (Asrt.*) statisch importiert und in Testfällen verwendet werden können. Vergleich primitiver Typen, z. B.: asrtequals(int expected, int actual) asrtequals(double expected, double actual, double delta) Delta als Toleranz beim Gleitkommavergleich Vergleich von Objekten, z. B.: asrtequals(object expected, Object actual) Vergleich erfolgt über equals()-methode asrtnotnull(object object) Bedingungen, z. B.: asrttrue(boolean condition) Alle Methoden existieren auch als Variante mit Fehlermeldung: asrttrue(string message, boolean condition) 15
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 die mit @Before oder @After annotiert werden. public class EuroTest { Euro dreieuro; @Before public void vorbereitung() { dreieuro = new Euro(3.0); @Test public void betrag() { asrtequals(3.0, dreieuro.getbetrag(), 0.001); @Test public void addieren() { Euro chseuro = dreieuro.addiere(dreieuro); asrtequals(6.0, chseuro.getbetrag(), 0.001); Wird vor jeder @Test-Methode erneut ausgeführt Wichtig: Methode muss public void und parameterlos in! Für die einmalige Ausführung von statischen Methoden vor bzw. nach allen Testfällen in einer Testklas existieren die Annotationen @BeforeClass und @AfterClass. 16
Erwartetete Ausnahmen Wenn eine Ausnahme (Exception) erwartet wird, kann die erwartete Ausnahme (bzw. ihr Class-Objekt) als Attribut expected der @Test- Annotation angegeben werden. @Test(expected=ArithmeticException.class) public void divisiondurchnull() { Division durch Null: hier wird eine int ergebnis = 3 / 0; ArithmeticException erwartet Der Testfall ist erfolglos (grüner Balken), wenn eine Ausnahme auftritt; tritt keine Ausnahme auf, ist der Test erfolgreich (roter Balken). 17
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.klas JUnit kann in beliebige Java-Programme eingebunden und Testfälle auf die Wei ausgeführt werden. Die Auswertung (und Anzeige) der Testergebnis muss in diem Fall vom aufrufenden Programm durchgeführt werden. import org.junit.runner.junitcore; import org.junit.runner.result; Beliebige Anzahl auszuführender Testklasn public class RunMyTests { public static void main(string[] args) { Result testresult = JUnitCore.runClass( EuroTest.class, NochEineTestklas.class); System.out.println("Fehler: " + testresult.getfailurecount()); Individuelle Auswertung 18
JUnit in Eclip: Einbindung Eclip unterstützt JUnit 4 von Haus aus. Die JUnit-Bibliothek kann über die Project Properties eingebunden werden. Wichtig: Version 4 von JUnit einbinden! 19
JUnit in Eclip: Ausführung Über Run As JUnit Test können einzelne Klasn (mit JUnit-Testfällen) oder ganze Pakete mit Testklasn als JUnit-Test ausgeführt werden Beispiel: Testklas mit insgesamt 7 Testfällen, von denen einer (parfehler) erfolgreich ist. 20
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 in, Mock-Objekte einzutzen. Mock-Objekte sind Attrappen: sie implementieren die gleiche Schnittstelle wie die echten Objekte und können die deshalb für den Test ertzen (und simulieren). In der Java API werden Schnittstellen intensiv verwendet. Die Voraustzungen 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
Mock-Objekte: Beispiel MockDatenbank +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 «interface» Datenbank +holepersonen(): List<Person> SQLDatenbank In der Anwendung wird nur gegen die Schnittstelle implementiert +holepersonen(): List<Person> 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