_home


Kerstin Dittert

Kerstin Dittert

kerstin.dittert@oocon.de
www.oocon.de

Wie wende ich JUnit effektiv an?

Organisation der Testfälle ---»

Klasse TestStarter implementieren ---»

Testfall neu anlegen ---»

Testfall ausführbar machen ---»

Testfall zu einer Test-Suite machen ---»

Testfall dem Testpaket hinzufügen ---»

Testpaket in die globale Test-Suite einbinden ---»

Testmethoden implementieren ---»

Test einer Bedingung ---»

Test der Fehlerbehandlung ---»

Testumgebung initialisieren und bereinigen ---»



Organisation der Testfälle

Die Testfälle werden rekursiv organisiert. Jedes Paket enthält eine Klasse TestPackage, welche alle Testfälle des Paketes als Test-Suite zusammenfasst. Die Test-Suiten aller Pakete werden wiederum in der Test-Suite TestProject für das gesamte Projekt zusammengefasst. Somit enthält diese Klasse alle Testfälle des Projektes. Mit Hilfe dieser Struktur können nach Bedarf unterschiedliche Teile des Projektes getestet werden:

  • eine Klasse (Ausführen eines TestCase),
  • ein Paket (Ausführen eines TestPackage),
  • das gesamte Projekt (Ausführen von TestProject).
_top

Klasse TestStarter implementieren

Diese Klasse startet die JUnit-GUI und führt automatisch eine Test-Suite aus. Sie wird benötigt, um einzelne Teile des Projektes (z.B. Klassen oder Pakete) unabhängig voneinander testen zu können.

import junit.ui.TestRunner;
public class TestStarter {

private TestRunner m_testRunner = null;

public TestStarter( String testName ) {

String[] tests = new String[1];
tests[0]=testName;
m_testRunner = new TestRunner();
m_testRunner.start(tests); }

}


_top

Testfall neu anlegen

Der neue Testfall wird von junit.framework.TestCase abgeleitet und im gleichen Paket wie die zu testende Klasse abgelegt. Als Namenskonvention hat sich Test<NameDerZuTestendenKlasse> bewährt. Innerhalb einer IDE werden dann die Testfälle im gleichen Paket und der gleichen Reihenfolge wie ihre zugehörigen Fachklassen angezeigt.

Beispiel

Anlegen des Testfall TestUser für die Klasse User im Paket demo.User

package demo.user;
import junit.framework.*;

public class TestUser extends TestCase
{ ... }


_top

Testfall ausführbar machen

Hierfür muss die main-Methode implementiert werden und die Klasse TestStarter mit dem Testfall aufgerufen werden.

Beispiel

Main-Methode des Testfall TestUser.

public static void main ( java. lang. String [ ] args) {

// Test-GUI starten, unter Angabe des voll qualifizierten Klassennamens
Teststarter tester = new TestStarter( "demo.user.TestUser" ); }

_top

Testfall zu einer Test-Suite machen

Im Testfall muss die suite-Methode implementiert werden. Hierdurch werden alle Methoden, die mit "test" beginnen, automatisch aufgerufen, wenn der Testfall ausgeführt wird. Der Testfall kann so im Projektfortschritt generisch erweitert werden.

Beispiel

suite-Methode des Testfall TestUser.

public static Test suite() {

// hinzufügen aller Testmethoden, beginnend mit test...
// Syntax: new TestSuite(<Klassenname>.class)
TestSuite suite = new TestSuite(TestUser.class);
return suite;

}


_top

Testfall einem Testpaket hinzufügen

Die Test-Suite TestPackage fasst alle Testfälle des Paketes zusammen. Sobald im Paket ein neuer Testfall angelegt wird, wird die suite-Methode dieser Klasse um den neuen Testfall erweitert.

Beispiel

Klasse TestPackage im Paket demo.user. Sie umfasst den Testfall TestUser.

package demo.user;
import junit.framework.*;

public class TestPackage extends TestCase {

public TestPackage(String name) {

super(name); }

public static Test suite() {

TestSuite suite= new TestSuite();

//suite.addTest(<vollQualifizierterKlassenname>.suite());
suite.addTest(demo.user.TestUser.suite());
suite.addTest(demo.user.TestUserProxy.suite());
return suite; }

public static void main(String[] args) {

TestStarter testStart = new TestStarter( "demo.user.TestPackage" ); }

}


_top

Testpaket in die globale Test-Suite einbinden

Die Test-Suite TestProject fasst alle Testfälle des Projektes zusammen. Sobald ein neues Paket angelegt wird, wird die suite-Methode dieser Klasse um das neue Testpaket erweitert.

Hinweis: das Anpassen dieser Klasse ist nur nötig, wenn das Paket (und damit das Testpaket) neu angelegt wurde. Werden nur neue Testfälle angelegt, so ist die Anpassung der Klasse TestPackage ausreichend!

Beispiel

Klasse TestProject im Paket dem. Sie umfasst das Testpaketdemo.user.TestPackage.

package demo;
import junit.framework.*;

public class TestProject extends TestCase {

public TestProject(String name) {

super(name); }

public static Test suite() {

TestSuite suite= new TestSuite();

//suite.addTest(<vollQualifizierterKlassenname>.suite());
suite.addTest(demo.user.TestPackage.suite());
suite.addTest(demo.controller.TestPackage.suite());
suite.addTest(demo.model.TestPackage.suite());
return suite; }

public static void main(String[] args) {

TestStarter testStart = new TestStarter( "demo.TestProject" ); }

}


_top

Testmethoden implementieren

Mit Hilfe des Reflection-API werden bei der Ausführung eines Testfalles alle Methoden, die mit "test" beginnen, automatisch aufgerufen.

Namenskonvention: test<NameDerZuTestendenMethode>, z.B. testGetNrOfUser für den Test der Methode getNrOfUser.

_top

Test einer Bedingung

Logische Bedingungen oder Gleichheit von Objekten werden mit Hilfe der assert-Methoden der TestCase-Klasse überprüft (siehe API-Beschreibung der Klassejunit.framework.TestCase).

Beispiele

Test auf Gleichheit mit boolschen Ausdrücken:

private User meierl = new User("Meier", "abc");
private User meier2 = new User("Meier", "hansdampf");
private User mueller1 = new User("Müller", "test");
private User muelller2 = new User ("Mueller", "abc");
private User mueller3 = new User("MUELLER", "abc");
private User mueller4 = new User("mueller", "sandsturm");
private User schmitz = new User("schmitz", "");

...

public void testEquals {

assertTrue( meier1.equals( meier2 ) );
assertTrue{ meier1.equals(mueller1) );
assertTrue( meier1.equals(new String()));
assertTrue ( meier1.equals(schmitz) );
assertTrue ( mueller2.equals(mueller3 ) );
assertTrue ( mueller2.equals(mueller4 ) );
assertTrue ( !mueller2.equals(muellerl) ) ;

// Eigenschaften der Aquivalenzrelation testen
// (siehe javadoc zu Object.equals() )

// reflexiv
assertTrue ( meier1.equals(meier1) );

// Symmetrie
if ( meier1.equals(meier2) )
assertTrue ( meier2.equals(meier1) ) ;

// Transisitivität
if ( mueller2.equals(mueller3) && mueller3.equals(mueller4) )
assertTrue (mueller2.equals(mueller4) ); }


Test auf Gleichheit mit numerischen Werten:

public void testRemoveAll() {

assertEquals( 3, liste.getNrOfUser());
liste.removeAll();
assertEquals( 0, liste.getNrOfUser() ); }


_top

Test der Fehlerbehandlung

JUnit ist hervorragend geeignet, um die Fehlerbehandlung zu testen. Wenn eine Exception erwartet wird, so wird diese in der Testmethode ohne weitere Verarbeitung gefangen. Nach dem Methodenaufruf, welcher die Exception werfen soll, wird mit Hilfe der fail-Methode ein Text ausgegeben. Dieser Text wird in der GUI nur angezeigt, wenn der Test fehlgeschlagen ist (d.h. die Exception wurde nicht geworfen).

Beispiele

Beim Instanziieren von User-Objekten kann eine IllegalArgumentException auftreten, falls Benutzername und Passwort null sind, oder falls der Benutzername leer ist.

public void testUser() {

try {
User abc = new User( null, null );
fail ("Sollte eine IllegalArgumentException werfen"); }
catch (IllegalArgumentException e) {};

try {
User abc = new User( "meier" , null );
fail ("Sollte eine IllegalArgumentException werfen"); }
catch (IllegalArgumentException e) {};

try {
User abc = new User( null, "abc" );
fail ("Sollte eine IllegalArgumentException werfen"); }
catch (IllegalArgumentException e) {};

try {

User abc = new User( "", "abc" );

fail ("Sollte eine IllegalArgumentException werfen"); }
catch (IllegalArgumentException e) {}; }


Beim Lesen von Benutzern kann eine UserNotFoundException auftreten.

public void testGetUser() {

liste.getUser( "meier" );

try {
liste.getUser( "testi" );
fail("Sollte eine UserNotFoundException werfen"); }
catch (UserNotFoundException e) {};
... }


_top

Testumgebung initialisieren und bereinigen

Da in den unterschiedlichen test...-Methoden einer Testklasse meist die gleiche Umgebung (Variablen, Ressourcen etc.) verwendet wird, ist es hilfreich diese Umgebung überall zu verwenden. Mit Hilfe der Methoden setUp und tearDown kann dies erzielt werden. setUp wird vor dem Ausführen einer test...-Methode aufgerufen, und tearDown nach jedem Testmethodenaufruf.

Beispiel

Beim Testen der Klasse UserContainer soll immer die gleiche Benutzer-Liste verwendet werden. Nach dem Durchführen einer test-Methode wird die Liste wieder geleert.

// Initialisierung der Testvariablen
protected void setUp() {

liste.addUser(meier1);
liste.addUser(mueller1);
liste.addUser(mueller2); }

// Zurücksetzen der Testvariablen
protected void tearDown() {

liste.removeAll(); }


_top