Ausführbare Spezifikationen für Java

Testing mit Jnario

Dr. Sebastian Benz

Jnario ist eine DSL mit eigener Syntax. Das bietet die Möglichkeit, neue Sprachkonstrukte einzuführen, die in einer normalen Programmiersprache wenig Sinn machen, aber beim Schreiben von Tests sehr hilfreich sind, zum Beispiel Tabellen (Listing 5). In diesem Beispiel definieren wir eine Tabelle mit den erwarteten Vorschlägen bei gegebenem Gang und der Geschwindigkeit. In unserem Fakt iterieren wir über die einzelnen Zeilen und prüfen die berechneten Werte. Wenn eines der Beispiele fehlschlägt, bekommen wir eine Fehlermeldung wie in Listing 6.

Listing 5

describe GearShiftProposal{
  def examples{
    | speed | currentGear | proposedGear |
    |   100 |      4      |      5       |
    |    80 |      3      |      4       |
    |    50 |      5      |      4       |
    |    10 |      3      |      2       |
  }
  fact examples.forEach[
    propsalFor(speed, currentGear) => proposedGear
  ]
  def propsalFor(int speed, int gear){
    new GearShiftProposal().calculate(speed, gear)
  }
}
Listing 6

java.lang.AssertionError: examples failed

        | speed     | currentGear     | proposedGear     |
        | 100       | 4               | 5                | ✓
        | 80        | 3               | 4                | ✓
        | 50        | 5               | 4                | ✘     (1)
        | 10        | 3               | 2                | ✓

(1) Expected new GearShiftProposal().calculate(speed, currentGear) => proposedGear but
         new GearShiftProposal().calculate(speed, currentGear) is 5
         new GearShiftProposal() is EconomicGearShiftProposal
         speed is 50
         currentGear is 5
         proposedGear is 4

Die Fehlermeldung demonstriert einen weiteren Vorteil von Jnario. Dadurch dass die Spezifikationen nach Java übersetzt werden, kann der Java-Code mit zusätzlichen Informationen angereichert werden, die Aufschluss darüber geben, warum eine Assertion fehlgeschlagen ist. Die Fehlermeldung beinhaltet den aktuellen Wert aller Teilausdrücke in der Assertion, das heißt, es ist nicht mehr notwendig, einen Test zu debuggen, um zu sehen, warum dieser fehlgeschlagen ist.

Tests als Dokumentation

Tests können ein effizienter Weg sein, um Software zu dokumentieren. So kann beispielsweise die Funktionsweise eines API leicht anhand von Beispielen in Testfällen dokumentiert werden. Der große Vorteil dieses Ansatzes ist, dass die Dokumentation während des automatisierten Builds ausgeführt wird und so immer sichergestellt ist, dass die Beispiele in der Dokumentation aktuell sind und funktionieren. Der Nachteil dieses Ansatzes ist, dass Testfälle schwerer lesbar sind als eine geschriebene Dokumentation. Jnario kombiniert beide Ansätze, indem eine HTML-Dokumentation aus den Spezifikationen generiert werden kann. Die Fakten werden dann als Codeschnipsel in die Dokumentation eingebettet. Zusätzlich gibt es bei Modulspezifikationen die Möglichkeit, diese mit Kommentaren anzureichern und mittels Markdown [8] zu formatieren. Abbildung 3 zeigt eine Beispielspezifikation für einen Stack mit der daraus generierten HTML-Dokumentation.

Abb. 3: Eine Spezifikation für einen Stack und die daraus generierte HTML-Dokumentation
Eine Sprache ist nur so gut wie ihre Toolunterstützung

Da Jnario eine domänenspezifische Sprache ist, sind während der Entwicklung keine Kompromisse in Bezug auf die Syntax notwendig. Das hat den Vorteil, dass Spezifikationen auf das Wesentliche reduziert sind und keinen syntaktischen Overhead enthalten. Das macht die Spezifikationen sehr lesbar und schnell zu erstellen. Ein gängiger Kritikpunkt bei domänenspezifischen Sprachen ist jedoch, dass die Werkzeugunterstützung nur unzureichend ist. Jnario wurde mit Xtext [9] entwickelt, einem Framework zur Entwicklung von DSLs. Dank Xtext verfügt Jnario über eine sehr gute Integration in Eclipse, mit inkrementellem Build, Editoren mit Syntax-Highlighting, Validierung und Autovervollständigung (Abb. 4). Das neueste Xtext-2.3-Release bietet jetzt auch eine Integration für JVM-basierte DSLs in die Eclipse Java Development Tools (JDT) an, sodass es unter anderem auch einen integrierten Debugger für Jnario gibt.

Abb. 4: Editieren von Features in Eclipse. Die Implementierung der einzelnen Schritte kann auf Knopfdruck versteckt werden, um die Lesbarkeit zu erhöhen
Zusammenfassung

Während der Entwicklung von Jnario wurden alle Tests direkt in Jnario geschrieben. Auch die Tutorials und Dokumentation auf der Webseite sind direkt aus diesen Spezifikationen generiert. Unsere Erfahrung hat gezeigt, dass sich mit Jnario das Verhalten von Anwendungen effektiv und schnell beschreiben lässt. Gleichzeitig unterstützt Jnario, darin das Potenzial von Testfällen stärker auszuschöpfen und diese als effektives Mittel für Design und Dokumentation einzusetzen. Ein großer Vorteil von Jnario ist, dass es leicht zu integrieren ist, da Spezifikationen in normale Java-Klassen kompiliert werden, die wiederum mit JUnit ausgeführt werden können. Jnario kann entweder als Eclipse-Plug-in über den Eclipse Marketplace [10] oder mittels Maven installiert werden. Fragen können jederzeit auf der Mailinglist [11] gestellt werden. Jnario ist Open Source [6] unter der Eclipse Public License und wird bei der BMW Car IT GmbH [7] aktiv von Sebastian Benz und Birgit Engelmann entwickelt.

Sebastian Benz ist Softwareentwickler bei der BMW Car IT GmbH. Seine Erfahrungen aus der Entwicklung unterschiedlicher DSLs und Testframeworks, die bei BMW im Einsatz sind, fließen nun in die Entwicklung von Jnario.
Geschrieben von
Dr. Sebastian Benz
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.