TracingChecker

Aus JACK Wiki
Zur Navigation springen Zur Suche springen

Der TracingChecker führt dynamische Tests auf Java Programmcode aus, die dem Prinzip von Unit-Tests folgen. Es müssen daher die zu prüfenden Dateien (“Source files”) sowie ein Testtreiber (“Test driver”) angegeben werden. Im Eintrag “Classes to trace” kann zudem eine kommaseparierte Liste von Klassennamen angegeben werden, für die während der Testausführung ein Trace erzeugt werden soll. Jeder ausgeführte Programmschritt in diesen Klassen wird dann in den Trace aufgenommen.

Beispiel einer Testklasse

Die Test-Klasse muss dem Grundgerüst des folgenden Programmcodes folgen.

import de.uni_due.s3.jack2.backend.checkers.tracingchecker.framework.TracingFramework;
import de.uni_due.s3.jack2.backend.checkers.tracingchecker.framework.TracingFramework.Test;

public class DemoprojektDynamisch {

    private int punkte = 0;

    public int getResult() {
        return punkte;
    }

    @Test(name="Test 1")
    public void test1() {

        Demoprojekt p = new Demoprojekt();

        float faktor1 = p.faktor("Andre", 36, 4, 10);
        float result1 = p.betrag(faktor1, 50000);

        if (result1 < 3207.78f || result1 > 3207.79f){
            if (faktor1 < 6.41f || faktor1 > 6.42f) {
                TracingFramework.printError("Falsches Ergebnis und falscher Faktor!");
            } else {
                TracingFramework.printError("Falsches Ergebnis, aber richtiger Faktor!");
                punkte += 20;
            }
        } else {
            punkte += 50;
        }
    }

    @Test(name="Test 2")
    public void test2() {
        // ...
    }
}


Die Klasse importiert das Tracing-Framework von JACK, das in der Datei “jack-tracing-framework.jar” bereitgestellt wird (Zeile 1 und 2). Die einzige Methode, die ein Testtreiber in jedem Fall anbieten muss, ist die Methode getResult(), die die erreichte Punktzahl von 0 bis 100 Punkten als Ganzzahl zurück gibt (Zeile 8-10). Zusätzlich kann der Testtreiber beliebig viele weitere, beliebig komplexe Methoden enthalten, die mit der Annotation @Test(name=“<Name_des_Testfalls>”) versehen werden (Zeile 12 und 32). Ist vor dem Start des gesamte dynamischen Tests eine einmalige Initialisierung notwendig, kann eine Methode init() ergänzt werden. Die Deklaration von zusätzlichen Hilfsmethoden und beliebigen Feldern ist zulässig.

Die Testmethoden werden in der Reihenfolge abgearbeitet, in der sie im Programmcode deklariert sind. Sie führen Aufrufe auf dem zu testenden Programmcode durch und vergleichen die Rückgaben mit den erwarteten Werten. Zur Erzeugung einer textuellen Rückmeldung an die Studierenden stellt das Tracing-Framework die Methode TracingFramework.printError(“<Meldung>”) bereit (Zeile 22 und 24). Wird eine solche Zeile erreicht, führt dies im Fehlerbericht von JACK zu einer Ausgabe der Form “Fehler in <Name_des_Testfalls>: <Meldung>”. Die Ausführung der Testmethode wird danach weiter fortgesetzt, d.h. eine Testmethode kann mehrere Meldungen erzeugen. Jede Meldung wird automatisch um einen Trace ergänzt, der die ausgeführten Programmschritte seit dem Start der Testmethode bis zur Erzeugung der Fehlermeldung erhält. Analog zur Erzeugung von Fehlermeldungen steht auch eine Methode TracingFramework.printWarning(“<Meldung>”) zur Verfügung. Diese erzeugt Ausgaben der Form “Warnung in <Name_des_Testfalls>: <Meldung>”. Treten während der Ausführung eines Testfalls Exceptions im geprüften Programmcode auf, führt dies automatisch zu einer Ausgabe der Form “Fehler in <Name_des_Testfalls>: <Beschreibung_der_Exception>". In diesem Fall wird die Ausführung der Testmethode abgebrochen und der dynamische Test mit dem Aufruf der nächsten Testmethode fortgesetzt. Auch bei einer Exception wird die Meldung um einen Trace ergänzt. Tritt hingegen eine Exception im Testtreiber auf, führt diese zu einem Abbruch des gesamten dynamischen Tests. Es wird keine Punktzahl vergeben, sondern die Lösung wird stattdessen mit einem “internal error” markiert. Die aufgetretene Exception wird als interne Fehlernachricht ausgegeben.Das Erzeugen der Traces zum Programmablauf führt zu einer signifikant verlängerten Laufzeit für die zu testenden Programme. Um den Server nicht zu lange mit einem einzelnen Test zu blockieren, ist die Erzeugung von Traces daher auf eine Länge von 500 Schritten begrenzt. Das Programm wird nach erreichen dieser Grenze weiter ausgeführt, aber es wird kein Trace mehr dazu aufgezeichnet. Die Traceaufzeichnung kann gezielter gesteuert werden, indem die Aufrufe TracingFramework.switchOffTracing() und TracingFramework.switchOnTracing() verwendet werden. Damit kann für Abschnitte eines Testfalls das zeitaufwändige Tracing abgeschaltet und später wieder eingeschaltet werden. Die Ein-/Ausschaltung gilt immer nur pro Testfall. Insbesondere beginnt jeder Testfall standardmäßig mit eingeschaltetem Tracing.

Schreibt der geprüfte Programmcode während der Testausführung Ausgaben auf die Standardausgabe, werden diese unabhängig von den einzelnen Testfällen gespeichert und als zusätzliche Information in der Web-Oberfläche von JACK mit ausgegeben. Eine automatische inhaltliche Auswertung der Ausgaben ist nicht möglich.