Die Java Assertions stellen ein gutes Hilfsmittel und eine sehr praktische Ergänzung zu Code-Dokumentation und für Unit-Tests dar. Bei der Verwendung mit Ant gibt es allerdings eines Stolperfalle.
Assertions im Schnelldurchgang
Mit Java Assertions ist es möglich, an beliebigen Stellen im Code Annahmen zu definieren, von denen man ausgeht, daß diese immer erfüllt sind. Ein kleines Beispiel dazu:
final Object someObject = someFactory.newObject();
assert someObjects != null;
Der Programmierer nimmt hier an, daß (per Schnittstellendefinition) die Factory immer ein Objekt liefert, nie einen null-Pointer. Diese Annahme wird durch die assert-Anweisung ausgedrückt.
Die asserts werden normalerweise von Java nicht ausgewertet. Erst über die Kommandozeilenoption „-ea“ (enable assertions) beim Start der Java VM werden diese aktiviert. Sollte jetzt der Fall auftreten, daß die Factory einen null-Pointer zurückliefert, so bricht das Programm mit einem AssertionError ab.
Assertions in Unit-Tests
Assertions sollten im Produktivcode deaktiviert, für Testläufe jedoch aktiviert sein.
Bei Unit-Tests können so einfach, je nachdem wo und wie Assertions eingesetzt werden, mehr Fehler erkannt werden, wie etwa fehlende case-Fälle in Verbindung mit einer Enum.
Dazu müssen jedoch, wie oben beschrieben, Assertions für die Unit-Tests aktiviert werden.
Stolperfalle in Ant
Bei Ant funktioniert dies nicht intuitiv. Ant kennt für die Tasks <java> und <junit> das Element <assertions>, über das die Assertions aktiviert werden können.
In Ant könnte ein Target wie folgt aussehen:
<target name="test" depends="...">
<junit>
<!-- Enable Java assertions -->
<assertions>
<enable />
</assertions>
<test name="foo.bar.SomeTestClass" todir="test-results" outfile="TEST-SomeTestClass">
...
</test>
</junit>
</target>
Junit führt die Tests aus foo.bar.SomeTestClass aus. Für die Ausführung wurden die Assertions aktiviert.
Müsste doch eigentlich funktionieren würde man meinen. Leider falsch. Ant läuft in einer Java VM, Junit wird in der gleichen VM ausgeführt. Die Einstellungen für die Assertions greifen nicht mehr!
Die Lösung ist einfach: Junit in einer separaten Java VM ausführen. Dazu einfach das Attribute fork=“true“ an den <junit>-Task anhängen:
<target name="test" depends="...">
<junit fork="true"> <!-- Starts Junit in a separate JVM -->
<!-- Enable Java assertions -->
<assertions>
<enable />
</assertions>
<test name="foo.bar.SomeTestClass" todir="test-results" outfile="TEST-SomeTestClass">
...
</test>
</junit>
</target>