JUnit und Eclipse

Ich nehm immer gerne die neuste Version einer Software. Vor allem wenn ich diese zum ersten Mal richtig benutze 🙂

So geschehen mit Eclipse und JUnit. Eclipse nutz ich in Version 3.4.2 und JUnit in 4.3.1. So weit so gut. Eclipse hat jetzt eine wunderbare Integration von JUnit. Man kann, in der Theorie, sowohl alle Tests einer Suite ausfĂĽhren, oder auch nur einen. Ausser man macht das so wie ich:

public class TestClient {
  public static junit.framework.Test suite() {
    return new JUnit4TestAdapter(RMITestClient.class);
}

  public static void main(String[] args) {
    junit.textui.TestRunner.run(suite());
  }

  @Test
  public void someTest {
    Value value = getSomeAction();
    assertTrue("should be true", value);
  }

  @Test
  public void someOtherTest {
    Value value = getSomeAction();
    assertTrue("should be true", value);
  }
}

So, wie man sieht, habe ich zwei Tests (mit der @Test-Annotation) und zwei Funktionen die die Abwärtskompatibiliät für JUnit <4.0 geben soll. Irgendwo ausm Internet[tm]. Nunja, mit diesen beiden Abwärtskompatibilitätsfunktionen kann die Eclipse-UI nicht mehr nur einzelne Tests ausführen, sondern führt den einen Test den man markiert aus, und dann den Rest trotzdem. Suboptimal. Deswegen einfach die Funktionen sich schenken, die Abwärtskompatibilität ebenso und dann klappt's auch mit den Nachbarn.

xUnit

Testen von Programmen ist wichtig. Das wurde schon recht frĂĽh erkannt. Ich hab ja schon frĂĽher ĂĽber Unit-Testing und Refactoring geschrieben. Jetzt les ich gerade das Buch „xUnit Test Patterns – Refactoring test code“ von Gerard Meszaros (ISBN-13: 978-0-13-149505-0). Dicker Schmöker mit knapp 890 Seiten. Ich werde hier jetzt ab und an ein paar Gedanken zu diesem Buch verfassen und wahrscheinlich auch Kapitelweise eine Zusammenfassung. Eigentlich dient das nur meinem Verständnis, aber vielleicht hat auch jemand anderes was davon 🙂

The Fragile Test Problem

In meinem Praxissemester bin ich ĂĽber WinRunner gestolpert. An sich eine schöne Idee, einfach ein paar Mausbewegungen und Klicks aufzeichnen und schauen ob auch das rauskommt, was rauskommen sollte. Scheitert aber schon an diversen Sachen, z.B. wenn man die Sprache im Programm umstellt. Zwar sollte sowas nicht die Funktionalität eines Programmes verändern, aber wer weiss, Bugs sind ĂĽberall. Meszaros kategorisiert das ganze (er nennt es „The Fragile Test Problem“) in vier Fallgruben aufgeteilt.

Behaviour Sensitivity

Wenn sich das Verhalten eines Systems ändert (weil sich z.b. die Anforderungen geändert haben), dann ist die Wahrscheinlichkeit, dass die Tests, die die geänderte Funktionalität prüfen, scheitern sehr gross (uff, was ein Satzbau). Das ist jetzt nichts spezielles für so Programme wie WinRunner, das ist immer so. Wenn ich bei einem Auto auf vier Reifen teste, die Requirements aber plötzlich ein Dreirad wollen, dann MUSS das schiefgehen. Richtig fies wird es erst, wenn wir uns auf die Funktionalität verlassen um das System in einen Status zu bringen, in dem wir einen Test ausführen.

Interface Sensitivity

Grundsätzlich ist das Testen einen Systems über die Benutzeroberfläche eine schlechte Idee. Jede minimale Änderung bringt jeden Test zum Scheitern. Und dies ist völlig unabhängig von der Benutzeroberfläche (GUIs wie QT oder GTK, CLI (Command Line Interfaces) oder Weboberflächen (Buzzword: Ajax, Web 2.0)).

Data Sensitivity

Alle Tests starten an einem Zeitpunkt, an dem bestimmte Konditionen gegeben sind. Irgendwelche Datenstrukturen sind vorhanden und werden genutzt. Solange man nich immensen Aufwand investiert um die Tests von diesen Daten unabhängig zu machen, ist es höchstwahrscheinlich das die Tests scheitern.

Context Sensitivity

Nachdem der Datenkontext schon wichtig ist, kommen natürlich noch andere externe EInflüsse dazu. Das können so simple Dinge wie die Uhrzeit sein (Sommer-/Winterzeitumstellung), aber auch Geräte wie Drucker oder Server.

All diese Abhängigkeiten machen das deterministische Wiederholen von Tests sehr, sehr schwierig. Natürlich gibt es viele Möglichkeiten diese Abhängigkeiten zu umgehen, aber egal welche Methode man nimmt, sie bleiben bestehen. Die xUnit-Familie stellt ein paar Muster zur Verfügung die uns einen grossen Grad an Kontrolle ermöglichen. Wir müssen nur noch lernen sie zu nutzen.

Dieses Testen wird ĂĽbrigens „regression testing“ genannt. Regression bedeutet auf Deutsch „RĂĽckwärtsbewegung“ und spiegelt das auch gut wieder. Wir haben ein fertiges Produkt und bewegen uns beim Testen von Vorne nach Hinten (Von der GUI zum Backend). Einen völlig anderen Ansatz spielt hier die testgetriebene Entwicklung (test-driven development), die das Prinzip umkehrt. Mittels dieser Methode wird eher das Verhalten von Software die noch geschrieben wird beschrieben, als die fertige Software rĂĽckwärts getestet.

Unit Testing

In der Softwareentwicklung gibt es, wie in jeder Ingenieursdisziplin, ein Vorgehensmodell wie komplexe Software am Besten erstellt werden sollte. Diese Planung trennt die einzelnen Schritte der Entwicklung in Teilprobleme auf, die dann weniger komplex und somit leichter zu beherrschen sind.

In der Softwareentwicklung gibt es derer fĂĽnf:

  1. Planung
  2. Analyse
  3. Design (Entwurf)
  4. Implementierung
  5. Validation und Verifikation

Ich werde hier nur auf den fĂĽnften Teil eingehen, fĂĽr die ersten Teile empfehle ich jetzt nur einfach spontan mal UMLet.
„Unit Testing“ weiterlesen