JUnit ist eines der wichtigsten Tools, die man als Java-Entwickler beherrschen sollte. Es erleichtert das Testen von Java-Klassen und ist zu 100% in Eclipse integriert! Anhand einer Beispiel-Klasse erkläre ich den Aufbau und die Funktionsweise von JUnit Test 4. Warum man eigentlich JUnit nutzen sollte, erläutert Jörg Hinrichs in seinem Artikel „Unit Tests: Zeitverschwendung?“.
Extrem schwer und darum kaum verwendete, teste ich heute die legendäre Rechteck-Klasse.
public class Rechteck { private int a; private int b; public Rechteck(int a, int b) { this.a = a; this.b = b; } public float berechneUmfang() { return 2 * b + 2 * a; } public float berechneInhalt() { return a * b; } }
Allgemein empfehle ich einen neuen Source-Ordner namens „test“ anzulegen und die ggf. vorhandene Paketstruktur zu übernehmen. Dies erhöht die Übersichtlichkeit und erleichtert die Testkoordination. In der folgenden Abbildung sieht man die neue Projekt-Struktur:
Um die Rechteck-Klasse zu testen, lege ich eine neue Klasse im Test-Source-Ordner an. Diese Klasse erhält den Zusatz „Test“, um sie von der ursprünglichen Klasse unterscheiden zu können. Die neue „RechteckTest“-Klasse wird nun um eine einfache Public-Methode „derTest1“ erweitert.
Um diese Methode als Testfall zu deklarieren, wird die Annotation „@Test“ über die Klasse geschrieben. Dies führt jedoch zu einem Compilerfehler. Um den Compilerfehler zu beheben, muss man die Bibliothek von JUnit 4 dem Projekt hinzufügen. (Links auf die Lampe klicken)
Innerhalb der neuen Methode „derTest1“ wird nun ein Testfall definiert. Die Prüfung, ob der Testfall positiv oder negativ ausgefallen ist, wird mittels der Assert-Klasse durchgeführt. Diese Klasse stellt verschiedene Methoden zur Verfügung um Objekte, Werte und Bedingungen zu prüfen. Im folgenden Beispiel teste ich die Berechnung des Umfangs eines Rechtecks. Hierzu lege ich mir ein Rechteck-Objekt an und lasse mir den Umfang berechnen. Vorab habe ich mir mithilfe der Testdaten (Länge: 10cm und Breite: 20cm) einen Wert von 60 cm ausgerechnet.
import org.junit.Assert; import org.junit.Test; public class RechteckTest { @Test public void derTest1() { Rechteck myRechteck = new Rechteck(10, 20); Assert.assertTrue(60 == myRechteck.berechneUmfang()); } }
Natürlich kann man auch andere Methoden der Assert-Klasse verwenden. Diese sind in der folgenden Tabelle aufgelistet:
Assert-Methode | Beispiel | Beschreibung |
---|---|---|
assertEquals(Object obj1, Object obj2) | assertEquals(new String(„hallo“), new String(„hallo“)) | Überprüft mittels der equals-Methode, ob zwei Objekte identisch sind. Hierzu muss die equals-Methode implementiert sein! Somit funktioniert diese Funktion auch mit Integer, Float, String oder Arrays. |
assertEquals(float value1, float value2, float dif) | assertEquals(0.2, 3.7, 4.0) | Vergleicht zwei Zahlenwerte, die nur eine bestimmte Differenz aufweisen dürfen. Wird eine größere Differenz festgestellt, wird „false“ zurück gegegeben. |
assertSame(Object obj1, Object obj2) | assertSame(myString, myString) | Checkt, ob zwei Referenzen auf das identische Objekte verweisen. |
assertNotSame(Object obj1, Object obj2) | assertNotSame(myString, myString2) | Checkt, ob zwei Referenzen nicht auf das identische Objekte verweisen. |
assertTrue(boolean condition) | assertFalse(3 == 3) | Prüft, ob die Bedingung richtig ist. |
assertFalse(boolean condition) | assertFalse(3 == 5) | Prüft, ob die Bedingung falsch ist. |
assertNull(Object obj) | assertNull(null) | Testet, ob das Objekt „null“ ist. |
assertNotNull(Object obj) | assertNotNull(new String()) | Testet, ob das Objekt nicht „null“ ist. |
Um einen Testlauf mit unserer Test-Klasse zu startet, brauchen wir nur eine lauffähige Eclipse Version. Hierzu selektiert man mit einem Rechtsklick die Test-Klasse und wählt im Kontextmenü unter dem Punkt „Run As“ den Eintrag „JUnit Test“ aus. Automatisch öffnet Eclipse die JUnit-Ansicht und zeigt das/die Ergebnisse des Testlaufs an.
Oftmals will man nicht ständig neue Objekte erschaffen, sondern sie über mehrere Testfälle hinweg weiter „bearbeiten“. Aus diesem Grund gibt es weitere Annotationen, die wir verwenden können. Die folgende Tabelle fast diese zusammen:
Annotation | Beschreibung |
---|---|
@Test | Kennzeichen für einen Testfall |
@Test(expected= Exception.class) | Kennzeichen für einen Testfall der eine Exception erwartet. |
@Test(timeout =x in ms) | Kennzeichen für einen Testfall, der in x ms erfüllt sein muss |
@Before | Wird vor jedem Testfall ausgeführt |
@After | Wird nach jedem Testfall ausgeführt |
@BeforeClass | Wird einmal vor der Test-Klasse ausgeführt |
@AfterClass | Wird einmal nach der Test-Klasse ausgeführt |
@Ignore(„Kommentar“) | Testfall wird nicht ausgeführt und der Kommentar angezeigt |
Wendet man die oben beschriebenen Annotationen an, ergibt sich folgende komplexe Test-Klasse:
import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class RechteckTest { private static Rechteck myRechteck; @BeforeClass public static void create() { // Test-Objekt erschaffen mit den Testwerten (Länge: 10 und Breite: 20) myRechteck = new Rechteck(10, 20); System.out.println("Start!"); } @Before public void vor() { // Diese Methode wird vor jedem Testfall ausgeführt System.out.println("vor Test"); } @Test public void derTest1() { // Testfall 1: Prüfung ob Umfangsberechnung stimmt System.out.println("Test1"); Assert.assertTrue(60 == myRechteck.berechneUmfang()); } @Test public void derTest2() { // Testfall 2: Prüfung ob Flächeninhaltsberechnung stimmt System.out.println("Test2"); Assert.assertNotNull(myRechteck.berechneInhalt()); } @After public void nach() { // Diese Methode wird nach jedem Testfall ausgeführt z.B. um einen bestimmten Zustand zu erreichen System.out.println("nach Test"); } @AfterClass public static void delete() { // Diese Methode wird am Ende der Test-Klasse ausgeführt z.B. zum aufräumen oder löschen von Rückständen System.out.println("Test Ende!"); } }
Start! vor Test Test1 nach Test vor Test Test2 nach Test Test Ende!
[download id=“6″ format=“2″]
Copyright © 2011 AxxG – Alexander Gräsel
Guter Post! Weiter so 😉
Danke für das Lob:-)
Super Beispiel, danke!
Danke. Echt gut geschrieben !
Danke!
Gutes Beispiel! ich habe noch eine kleine Frage.. wieso schreibst du Assert.assertEquals? also wieso der erster Assert? braucht man das, damit auf die importierte JUnit Library Class refenziert wird, also wie ein normaler methodenaufruf… Klasse.methode..
Gibt es den Eingangs verlinkten Artikel „Unit Tests: Zeitverschwendung?“ noch irgendwo zu lesen? Entweder trollt mich nämlich Gockel oder aber die Website wurde vom Netz genommen. Sie lässt sich nämlich nicht mehr öffnen HTTP 500 Error.
Hallo Norman,
kein tut mir Leid, die Seite scheint offline zu sein.