Home ORDIX AG             Dienstleistung             Trainingsshop    Kunden / Referenzen Aktuelles    Kontakt
Home  Pfeil  ORDIX News  Pfeil  3/2007  Pfeil  Java/J2EE/JEE
suche: 
Dieser Artikel richtet sich an Softwareentwickler, die mit Java 5 oder höher arbeiten und mittels Unit-Tests die Korrektheit ihres Programmcodes überprüfen möchten.

Glossar

ant
ant ist ein in Java geschriebenes Werkzeug zur automatisierten Abarbeitung von Aufgaben (Dateien kopieren, Sourcen kompilieren, Archive packen etc.). Welche Aufgaben in welcher Reihenfolge mit welchen Parametern ausgeführt werden, wird in so genannten ant-Skripten abgelegt, die XML als Format verwenden. ant ist vor allem in der Softwareentwicklung weit verbreitet und wird von fast allen IDEs unterstützt.
Eclipse
Open Source Entwicklungsumgebung unter Verwaltung der Eclipse Foundation. Entstanden aus dem kommerziellen „Visual Age for Java" von IBM.
JUnit
Ein Open Source Framework zur Durchführung von automatisierten Tests von Java-Programmen.
JDK
Java Development Kit. JDK ist eine Sammlung von Tools von Sun Microsystems für die Entwicklung von Java-Programmen.
IDE
Integrated Development Environment. Eine IDE ist eine graphische Oberfläche für eine komfortable Software-Entwicklung. Z. B. Eclipse ist eine Java-IDE.


Testen mit JUnit 4

JUnit, die Vierte


Kein Softwareentwicklungsprojekt kommt heute ohne Unit-Tests aus. Gerade im Bereich Java erfreut sich ein Tool mit dem Namen JUnit sehr großer Beliebtheit. Es ist seit einem Jahr in der Version 4 verfügbar. Daher ist es an der Zeit, seine Neuerungen in Bezug auf die aktuelle Java-Version unter die Lupe zu nehmen und auf Basis unserer Erfahrungen aus der Praxis zu bewerten.

JUnit

Bei JUnit handelt es sich um ein Testing Framework für „wiederausführbare Tests", das besonders in der testgetriebenen Entwicklung und als Methode im „Extreme Programming" (XP) zum Einsatz kommt. Die Software wurde von Kent Beck, Mitbegründer von „Extreme Programming", und Erich Gamma, einem der legendären „Gang Of Four", entwickelt und dient zum Schreiben von Unit-Tests in Java. JUnit ist Open Source Software unter der Common Public License und liegt derzeit in der Version 4.3.1 zum Download vor [1].

Neuerungen

Zu den wohl wichtigsten Neuerungen der aktuellen Version gehört die Zusammenarbeit mit Java 5 oder höher und damit verbunden die Benutzung von Annotations, eines der neuen Sprachmittel des Tiger-Releases von SUN.

Abbildung 1 zeigt ein Beispiel mit den Möglichkeiten eines JUnit-Tests. Diese werden im Folgenden noch detailliert dargestellt.

import static org.junit.Assert.assertEquals;


import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;


public class CalculatorUtilTest {


  private static final Long number1 = null;
  private static final Long number2 = new Long(1);
  private static final Long number3 = new Long(2);


  @BeforeClass
  public static void setUpBeforeClass() throws Exception { ... }


  @AfterClass
  public static void tearDownAfterClass() throws Exception { ... }


  @Before
  public void setUp() throws Exception  { ... }


  @After
  public void tearDown() throws Exception { ... }


  @Test
  public void testSubtract_Zero() {
    assertEquals(new Long(0), CalculatorUtil.subtract(number3, number3));
  }


  @Test(timeout = 1)
  public void testSubtract_Timeout() {
    try {
      Thread.sleep(10000);
    } catch (InterruptedException e) {
      // TODO
      e.printStackTrace();
    }
    assertEquals(new Long(1), CalculatorUtil.subtract(number3, number2));
  }


  @Test
  @Ignore
  public void testSubtract_Ignore() {
    assertEquals(new Long(2), CalculatorUtil.subtract(number3, number1));
  }


  @Test(expected = NullPointerException.class)
  public void testSubtract_Exception() {
    assertEquals(new Long(2), CalculatorUtil.subtract(number1, number1));
  }
}
Abb. 1: Beispiel für die Möglichkeiten eines JUnit-Tests.

Damals

Diejenigen Leser unter Ihnen, die noch mit JUnit 3 aufgewachsen sind, werden wissen, wie ein Testfall im Regelfall aufgebaut ist. Für alle anderen hier noch einmal ein kurzer Abriss:

  1. Von junit.framework.TestCase mussten die Testklassen abgeleitet werden.
  2. Jede Testmethode hatte ein vorangestelltes test im Methodennamen, z. B. testMyMethod.
  3. Tatsächliche Ergebnisse mit erwarteten Ergebnissen wurden über diverse Assert-Methoden (der Klasse TestCase) verglichen.

Heute

Mit Einführung der neuen Version von JUnit gelten nun die folgenden Regeln:

  1. Normale Klassendefinition ohne TestCase-Ableitung.
  2. Testmethoden brauchen kein Präfix test mehr.
  3. Testmethoden werden mit @Test Annotation gekennzeichnet (dafür notwendig: import org.junit.Test).
  4. Weiterhin werden, wie bei JUnit 3, Assert-Methoden für Vergleichszwecke benutzt. Diese sind jetzt allerdings statische Methoden der Klasse Assert und lassen sich so sehr einfach nutzen, wenn man eine entsprechende Import-Anweisung benutzt.

Vor- und Nachbereiter einer Methode

Zwei weitere Annotations unterstützen den Aufbau (Start) bzw. den Abbau (Stopp) von Tests. Diese ersetzen die Methoden setUp() und tearDown() von JUnit 3 und dienen demselben Zweck:

Für die Namensgebung der Methodennamen selbst existieren keine Namenskonventionen. Es können beliebig viele @Before- und @After-Methoden in einer Testklasse vorhanden sein. Dabei können diese auch vererbt werden.

Beim Ausführen einer Testklasse werden immer zuerst die @Before-Methoden der Superklasse und dann die geerbten (also die eigenen) aufgerufen. Bei den @After-Methoden sind es zuerst die eigenen und anschließend die der Superklasse.

Vor- und Nachbereiter einer Klasse

Methoden mit @BeforeClass und @AfterClass Annotation werden nur einmal zu Beginn eines Tests beziehungsweise am Ende ausgeführt. Zu vergleichen sind sie mit der TestSetup-Klasse aus dem alten JUnit Extensions Package. Sie dürfen in einer Testklasse im Gegensatz zu @Before und @After nur ein einziges Mal vorkommen. Die beiden Annotations @BeforeClass und @AfterClass werden verwendet, um Tests vorzubereiten; beispielsweise um eine DB-Verbindung aufzubauen bzw. abzubauen und allgemein Ressourcen zu reservieren oder freizugeben.

Tests mit Exception-Parameter

Die eben schon beschriebene @Test Annotation macht nun auch das Überprüfen von Exceptions sehr einfach. Über einen Parameter kann die erwartete Exception angegeben werden.

Ein Beispiel:
@Test(expected=NullPointerException .class). Der Test läuft nur korrekt durch, wenn genau die angegebene Exception ausgeworfen wird. Bei keiner oder einer anderen Exception zeigt der Testfall einen Fehler an.

Abb. 2: Entwicklungsumgebung Eclipse nach erfolgreicher Testdurchführung. (vergrößern)
 
Abb. 3: Auswahlmöglichkeiten bei der Erstellung eines neuen JUnit-Tests. (vergrößern)

Tests mit Timeout-Parameter

Ein weiterer Parameter, der der @Test-Annotation übergeben werden kann, ist ein Timeout in Millisekunden.

Ein Beispiel:
@Test(timeout=60000). Dieser Test wird nach einer Minute automatisch abgebrochen und als verfehlt protokolliert.

Ein Beispiel

Das Programm aus Abbildung 2 zeigt einen vollständigen Unit-Test mit JUnit 4. Er testet eine Subtraktionsmethode, die als Beispiel im ORDIX News Artikel „Java unterm Kleeblatt" [2] genannt wurde. Dort kam übrigens JUnit 3 zum Einsatz. Das Beispiel gibt einen Über blick über die Nutzungsmöglichkeiten der oben beschriebenen Annotations.

Ignorieren von Tests

Die Annotation @Ignore mit optionalem Kommentar-Parameter, z. B. @Ignore("Queue im Message Broker fehlt"), ignoriert einen JUnit-Test und protokolliert dies im Report. Dies kann nützlich sein, wenn aufwendige Tests während der Entwicklung kurzzeitig deaktiviert werden sollen, ohne sie zu löschen oder auszukommentieren. Dank dieser nützlichen Funktion geraten diese Tests nicht in Vergessenheit, schon allein, weil sie in den Reports auftauchen.

Einbindung in Eclipse

Neben der klassischen Verwendung von JUnit auf der Kommandozeile, eignet es sich hervorragend zur Integration in Entwicklungsumgebungen. Dies soll im Folgenden am Beispiel der weit verbreiteten und sehr beliebten IDE Eclipse [3] gezeigt werden. JUnit wird zwar schon mit dem Eclipse Bundle ausgeliefert, allerdings ist die alte Version voreingestellt.

Um nun für eine Java-Klasse einen neuen Unit-Test zu erzeugen, wird im Package Browser oder Navigator im Kontextmenü der entsprechenden Klasse der Menüpunkt „New JUnit Test Case" oder alternativ über das Menü File -> New ... -> JUnit Test Case, gewählt. Im daraufhin erscheinenden Dialogfenster kann zwischen „New JUnit 3.8.1 test" und „New JUnit 4 test" gewählt werden. Egal für welche Version man sich entscheidet, es müssen die Bibliotheken für JUnit in den Buildpath mit aufgenommen werden. Diese werden schon mitgeliefert und müssen nur noch bestätigt werden.

Welche Auswahlmöglichkeiten es im Assistenten für die Erstellung eines neuen Tests gibt, zeigt Abbildung 3, während die Abbildung 2 einen erfolgreich absolvierten Unit-Test in Eclipse repräsentiert.

Kompatibilität

Sollen neue JUnit-4-Tests mit dem alten JUnit-Runner ausgeführt werden, so ist eine Ergänzung im jeweiligen Test vorzunehmen (siehe Abbildung 4).

public static junit.framework.Test suite() {
   return new JUnit4Adapter(ThisClass.class);
}
Abb. 4: Ergänzung bei JUnit-4-Tests mit dem alten JUnit-Runner.

Um alte Tests mit dem neuen JUnit-4-Runner auszuführen, ist nichts zu tun, denn JUnit 4 ist abwärtskompatibel.

Fazit

Die neue Version des Test Frameworks JUnit wurde gegenüber der Version 3 um einige Funktionen erweitert und verbessert. Die Erstellung von Unit-Tests ist durch den Einsatz der Java 5 Sprachfunktion Annotations viel komfortabler geworden. Allerdings war dies auch bitter nötig, um nicht zu viele Entwickler an die Konkurrenz aus dem Open Source-Lager von TestNG [4] zu verlieren.

Ein Umstieg ist in jedem Fall sinnvoll und nicht sehr aufwendig, da die Weiterverwendung durch die Abwärtskompatibilität des Produkts weiterhin gewährleistet ist. Lesen Sie hierzu auch den ORDIX News Artikel "JUnit 4 im Expertencheck".

Andre Dirr (info@ordix.de).