Unit-Tests mit JUnit 5
Unit Test
- Ein Unit-Test testet eine kleine selbständige Einheit (Unit) der Software, z. B. eine Klasse, ein API, ein Modul
- Der Test versucht die Unit möglichst isoliert zu testen
- Unit Test werden häufig vom Entwickler selbst geschrieben
- Unit Tests sind ein wichtiger Teil der Testgetriebenen Entwicklung
- Für Java ist das gängigste Unit-Test-Framework JUnit
http://www.junit.org
Eine detaillierte Einführung in das Schreiben von Unit-Tests kann hier aus Zeitgründen nicht gegeben werden. In der Praxis gibt es eine ganze Reihe von Hilfsmitteln, um die zu testende Einheit zu isolieren und dann einzeln zu testen. Hierzu gehören Mocks, Stubs, Test Harness etc.
Die Testgetriebene Entwicklung (test-driven development) (TDD) ist eine Methode, die häufig bei der agilen Entwicklung von Computerprogrammen eingesetzt wird. Hier erstellt die Software-Entwickler:innen die Tests grundsätzlich vor den zu testenden Komponenten.
Die Menge der Tests, die zusammengehören, nennt man Test-Suite.
JUnit Annotations
- JUnit 5 arbeitet mit Annotations, sodass man keine Klassen ableiten oder Interfaces implementieren muss
- Man annotiert parameterlose Methoden und macht sie hierdurch zu Tests bzw. Hilfsmethoden für die Tests
- Die wichtigsten Annotations sind
@Test
– Kennzeichnet eine Methode als Test@BeforeEach
– Methode wird vor den Tests ausgeführt (Test-Setup)@AfterEach
– Methode wird nach den Tests ausgeführt (Test-Teardown)@Disabled
– Test wird (temporär) ignoriert und nicht ausgeführt@DisplayName
– Name der Methode in der Anzeige
Annotationen sind ein Java-Feature, das es erlaubt Klassen, Methoden und Attribute mit zusätzlichen Informationen zu versehen, die dann von anderen Klassen ausgewertet werden können. Eine Annotation verändert nicht das Verhalten eine Methode, liefert aber Meta-Informationen über diese. Man kann sich Annotationen grob als Kommentare vorstellen, die maschinenlesbar sind, d. h. die vom Programm selbst oder dem Compiler wieder ausgewertet werden können.
JUnit Assertions
- Die Erwartungen des Tests drückt man durch Assertions aus
- Die Assertions liegen in der Klasse
org.junit.jupiter
.api.Assertions
Assertion | Bedeutung |
---|---|
assertArrayEquals | Elemente des Arrays sind gleich |
assertEquals , assertNotEquals | Parameter sind gleich / ungleich |
assertSame , assertNotSame | Objekte sind identisch / nicht identisch |
assertNull , assertNotNull | Referenz ist null / nicht null |
assertTrue , assertFalse | Bedingung ist wahr / falsch |
fail | Schlägt auf jeden Fall fehl |
Eine Zusicherung oder Assertion (lateinisch/englisch für Aussage, Behauptung) ist eine Aussage über den Zustand eines Computer-Programms. Mithilfe von Zusicherungen können logische Fehler im Programm erkannt und das Programm kontrolliert beendet werden. Des Weiteren können Assertions Informationen über den Grad der Testabdeckung während der Verifikation liefern. Quelle: Wikipedia
Beispiel: Unit die getestet werden soll
public class KomplexeZahl {
public KomplexeZahl(double re, double im) { ... }
public double getRe() { ... }
public double getIm() { ... }
public KomplexeZahl addiere(KomplexeZahl z) { ... }
public KomplexeZahl subtrahiere(KomplexeZahl z) { ... }
public KomplexeZahl multipliziere(KomplexeZahl z) { ... }
public KomplexeZahl dividiere(KomplexeZahl z) { ... }
public int hashCode() { ... }
public boolean equals(Object obj) { ... }
public String toString() { ... }
}
Die Klasse repräsentiert eine Komplexe Zahl und erlaubt es, mit diesen Zahlen einfache arithmetische Operationen durchzuführen. Die Implementierung ist hier weggelassen, da es für die Tests ausschließlich um die Schnittstelle, also die nach außen hin sichtbaren Methoden geht.
Beispiel: Unit-Test ohne JUnit
public class KomplexTest {
public void testAddition() {
KomplexeZahl k1 = new KomplexeZahl(3, 2);
KomplexeZahl k2 = new KomplexeZahl(5, 5);
if (k1.addiere(k2).equals(new KomplexeZahl(8, 7))) {
System.out.println("OK: Addition");
}
else {
System.err.println("Fehler: Addition");
}
}
public static void main(String[] args) {
KomplexTest test = new KomplexTest();
test.testAddition();
}
}
Man kann Tests auch ohne entsprechendes Framework entwickeln, wie das obige Beispiel zeigt. Der Nachteil ist aber, dass man in diesem Fall selbst die Ausgaben kontrollieren muss und entscheiden, ob ein Fehler vorliegt oder nicht. Bei größeren Programmen oder häufigen Testläufen kann dies sehr mühsam werden.
Beispiel: Unit-Test mit JUnit
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
public class KomplexeZahlTest {
@Test
void testAddition() {
KomplexeZahl k1 = new KomplexeZahl(3, 2);
KomplexeZahl k2 = new KomplexeZahl(5, 5);
assertEquals(new KomplexeZahl(8, 7), k1.addiere(k2));
}
}
Der Test wird deutlich einfacher, wenn man das JUnit-Framework einsetzt. Zum einen kann man die Erwartungen an die korrekte Programmausführung klarer erkennen, da sie nicht mehr in einem if
versteckt ist, sondern durch das assertEquals(new KomplexeZahl(8, 7), k1.addiere(k2))
formuliert wird. Zum anderen wird der Test viel kürzer und kann jetzt automatisch ausgewertet werden. Die Entwickler:innen müssen nicht mehr auf jede einzelne Ausgabe schauen, es reicht sich das Gesamtergebnis anzusehen.
Bei JUnit 5 müssen die Testmethoden nicht mehr public
sein, wie noch bei JUnit 4.
JUnit und Pflichtübungen
- Es wird erwartet, dass Sie in den Pflichtübungen die Funktionalität Ihres Programms mit JUnit-Tests nachweisen
- Abgaben, bei denen die eigenen JUnit-Tests nicht funktionieren gelten als nicht bestanden
- Verwenden Sie bitte JUnit 5 und keine ältere Version
Sie können JUnit ganz einfach als Library Ihrem Eclipse-Projekt hinzufügen. Gehen Sie hierzu mit der rechten Maustaste auf das Projekt und wählen Sie „Properties“. Wählen Sie im Dialog dann „Java Build Path“, „Libraries“ und klicken Sie auf „Add Library“.

Wählen Sie im Folgenden Dialog „Junit“ aus und klicken Sie auf „Next“.

Nun wählen Sie „Junit 5“ und klicken auf „Finish“.
