Unit Tests: Wohin damit…?

In Java (und nicht nur dort!) sollten Unit-Tests geschrieben werden, und das bekannteste Werzeug dafür ist JUnit. Gewöhnlich wird eine Testclasse pro Javaclasse erstellt. Aber wo in der Orderhierarchie sollten die Testclassen untergebracht werden? Dieser Artikel diskutiert zwei übliche Ordnerstrukturen, und eine dritte Möglichkeit, von der ich letzes Wochenende auf einer Konferenz in Boston erfahren…

Full Article

Warum ist es überhaupt wichtig, wo wir die Unit Tests unterbringen? Weil wir die kleinste “Einheit” (Unit) des Systems testen wollen, und die kleinste Einheiten (Klassen, Methoden und Constructoren) sind oft package private oder protected, und nicht immer public. Um leicht auf diese Elemente zugreifen zu können, sollte der Testcode in der selben Package sein. Das gibt uns zwar keinen Zugang zu privaten Variablen und Funktionen, aber wenn die zum Testen notwendig wären, sollte die Architektur der Klasse überprüft werden. Die naive Klassenstruktur wäre dann folgendermaßen:

 src/de/jastram/unit/MyClass.java src/de/jastram/unit/MyClassTest.java 

Mir gefällt diese Struktur nicht (und viele andere Entwickler stimmen mir zu), weil nun der Ordner normalen und Testcode mischt. Das ist aus vielerlei Gründen schlecht: JavaDoc würde die Testklassen enthalten, es ist schwierig, eine Distributionsdatei ohne Testklassen zu erstellen, usw. Diese Probleme könnten zwar mit einem geschickten Ant Skript gelöst werden, aber das Resultat ist nicht elegant, und für neue Entwickler schwer zu verstehen.

Die zweite Lösung gfällt mir wesentlich besser, und ist meine Empfehlung: Testklassen sind in der selben Package, aber in unterschiedlichen Ordnern:

 src/de/jastram/unit/MyClass.java test/de/jastram/unit/MyClassTest.java 

Alle IDEs die ich kenne, unterstützen diese Struktur, und Ant Skripte sowieso. Es ist nicht unüblich, eine Reihe von Sourceverzeichnissen zu haben. Jetzt ist es kinderleicht, JavaDoc zu erzeugen, oder eine JAR ohne die Testklassen zu bauen. Aber diese Struktur läßt zwei Fragen offen: (1) Was tun, wenn wir aus irgendeinem Grund doch Zugang zu privaten Elementen haben wollen, und (2) ist diese Struktur nicht ein bißchen übertrieben für kleine Projekte?

Für Punkt 1 gibt es eine Lösung (auch ohne Reflektion): Wir bringen die Testklasse einfach als static Memberklasse in unserer Hauptklasse unter! Das ist auch eine gute Struktur für Demonstrationen, weil wir nur eine einzige Klasse haben:

 src/de/jastram/unit/MyClass.java 

Und wo ist die Testklasse? In der selben Datei – der Code sieht etwa folgendermaßen aus:

public class MyClass { ... public static class Test extends TestCase { ... } } 

Und wie gesagt, nun können wir sogar auf die privaten Elemente zugreifen. Wie gesagt, diese Architektur muß mit Vorsicht genossen werden, und ist nicht für größere Projekte geeignet. Es ist (fast) unmöglich, das Programm ohne den Testcode zu verarbeiten, es ist noch nicht einmal möglich, die Datei ohne den Testcode zu drucken! Dennoch, für kleine Tests und Demos ist das eine prima Architektur.

Gibt es vielleicht noch bessere Ansätze zur Codeorganisation? Schreibt Eure Meinung weiter unten ins Formum!