Terminal-Testklasse

Terminal.java

Moritz Halm hat eine einfache Klasse geschrieben, die dazu verwendet werden kann, Programme, die die Terminal-Klasse des Lehrstuhls für ihre Ein- und Ausgabe nutzen, zu testen. Dabei erlaubt sie es, die Matcher der Hamcrest-Bibliothek zu verwenden, wodurch sie trotz ihrer Einfachheit sehr flexibel ist.

TL;DR: Beispielprojekt

Wer sich direkt am Code ansehen will, wie das Ganze funktioniert, kann sich einfach das Beispielprojekt herunterladen und in Eclipse importieren. Das Projekt kann auch gut als Vorlage für das eigene Projekt dienen.

Einrichtung

Statt der Terminal-Klasse der Vorlesung wird unsere Klasse Terminal.java in das Projekt gelegt. Wenn sie nicht in den Test-Modus versetzt wird, verhält sich die Klasse genau wie die Terminal-Klasse des SDQs. Somit kann auch weiterhin im Terminal mit dem Programm interagiert werden.

JUnit und Hamcrest

Um JUnit zum Testen zu verwenden, wird wie üblich JUnit zum Eclipse-Projekt hinzugefügt:

Die Testklasse wird erst dadurch mächtig, dass man die Matcher-Bibliothek Hamcrest verwendet, um die erwartete Ausgabe zu spezifizieren. Dieses wird wie folgt in’s Eclipse-Projekt eingebunden:

Eine gute Einführung zu Hamcrests Matchern gibt es von Vogella, eine detaillierte Anleitung um eigene Matcher zu schreiben, gibt es bei planetgeek.ch. Um alle Hamcrest-Matcher auf einmal zu importieren, verwendet man am besten diesen statischen Import:

import static org.hamcrest.Matchers.*;

Optional: Quelltext und Javadoc von Hamcrest mit einbinden

Damit Eclipse die Dokumentation der Hamcrest-Bibliothek anzeigt, muss deren Quelltext eingebunden werden:

Verwendung

Ein kleines Beispiel dafür, wie die Testklasse verwendet werden kann, ist in der Klasse ExampleTest zu finden.

Testmodus anschalten

Um mit der Klasse testen zu können, muss sie erst in den Test-Modus versetzt werden. Das geht am besten in einer mit @BeforeClass annotierten Methode:

@BeforeClass
public static void enableTerminalTestingMode() {
	Terminal.enableTestingMode();
}

Ein- und Ausgabe spezifizieren

Nun wird Befehl für Befehl die Eingabe spezifiziert und dabei angegeben, welche Ausgabe der Befehl haben soll. Hierzu stehen diese Methoden zur Verfügung:

#addMultipleLineOutputThatMatches(String, Matcher<? super List<String>>)Für ein Befehl, der mehrere Zeilen ausgeben kann. Als zweites Argument wird ein Matcher für die Liste an ausgegebenen Zeilen angegeben.

#addMultipleLinesOutputThatIsExactly(String, String... lines)Für einen Befehl, der mehrere Zeilen ausgeben kann. Als zweites Argument wird genau angegeben, welche Zeilen erwartet werden.

#addSingleLineOutputThatMatches(String, Matcher<String>)Für einen Befehl der genau eine Zeile ausgeben soll. Als zweites Argument wird ein Matcher für diese Zeile angegeben.

#addSingleLineOutputThatIsExactly(String, String)Für einen Befehl der genau die im zweiten Argument angegebene Zeile ausgeben soll.

#addNoOutput(String)Für einen Befehl, der keine Ausgabe haben soll.

Aufräumen

Nach einem Durchlauf muss die Ausgabe des letzten Befehls überprüft und dann das Terminal wieder zurück auf Anfang gesetzt werden. Das geht am einfachsten in einer mit @After annotierten Methode:

@After
public void cleanUp() {
	Terminal.flush();
	Terminal.reset();
}

Dank

Die Idee für diese einfache Testklasse stammt von Moritz Halm. Ich möchte ihm dafür danken, dass er sie hier zur Verfügung stellt. Niels Philipp Modry hat eine einfach Verbesserung der Klasse zur Verfügung gestellt, die es erlaubt, mehrere Zeilen auch mit nur einen Aufruf an Terminal#printLine auszugeben. Dafür möchte ich auch ihm danken.

Fortgeschrittenes

Die Testklasse ist trotz ihrer Einfachheit sehr mächtig. Es sollte damit möglich sein, alle Anforderungen abzubilden, die an Programme im Rahmen von Aufgaben der Vorlesung gestellt werden. Trotzdem gibt es ein paar Einschränkungen:

Ich habe im ersten Semester eine Test-Bibliothek geschrieben, das diese Probleme angeht: Jede Ausführung erfolgt in einem eigenen ClassLoader und eigene Matcher sorgen für detaillierte Fehlermeldungen. Die Bibliothek schießt allerdings eher mit Kanonen auf Spatzen. Sollte sich trotzdem jemand dafür interessieren, findet man sie hier: git.joshuagleitze.de/progtutors/submissiontest.