Zum Hauptinhalt springen

Test Result Exchange XML (TREX)

TREX ist ein am Apache Ant JUnit XML orientiertes Austauschformat für Testergebnisse. Es dient dazu, die sprach- und technologieabhängige Repräsentation von Testergebnissen in ein standardisiertes Format zu überführen.

Die übergeordneten Ziele des Formats sind:

  • Einheitliche Darstellungsmöglichkeit in der Weboberfläche von Subato
  • Verwendung sowie Vergleichbarkeit bei der Auswertung von Forschungsdaten.

Grund für das Format ist, dass es bisher keinen Standard für JUnit XML gibt und bei der automatischen Auswertung von Programmieraufgaben weitere Aspekte kodiert werden müssen, die bei einem professionellen Einsatz kaum (oder gar nicht) anfallen würden. In diesem Repo gibt es weitere Infos zu den unterschiedlichen Flavors von JUnit XML.

Gemeinsamkeiten und Unterschiede zu Apache Ant JUnit XML

Das Format ist kompatibel. Es wird allerdings nur eine Teilmenge an Attributen/Elementen in Eva genutzt und es werden werden weitere eigene Elemente ergänzt. Folgende Entscheidungen wurden beim neuen Format festgehalten:

  • Kompatibilität zu Apache Ant JUnit XML, da weit verbreitet und für viele Programmiersprachen Bibliotheken existieren, die in dieses Format exportieren.
  • Informationen sollen jederzeit im Dokument erscheinen können. So kann Generierung der XML streambasiert (ohne zurückspringen) erfolgen. z.B. durch storage-Element. Man könnte auch im Wurzelelement die Informationen speichern, allerdings kennt man diese erst nach Ausführung aller Testfälle.
  • Denormalisierung (durch Zusammenfassungen wie z.B. Anzahl ausgeführter Tests) vermeiden, wo möglich. Fehlerquelle für Inkonsistenzen.

Neu:

  • storage-Element
  • system-out und system-err Elemente pro testcase (bereits in anderen Tools genutzt)
  • pending und started Elemente (für zusätzliche Testfall Zustände/Ergebnisse)

Limitierungen:

  • Testfälle können theoretisch geskippt werden. Das bildet das Format derzeit nicht ab.

Aufbau

trex.xml
<?xml version="1.0" encoding="UTF-8" ?>
<testsuite timestamp="2023-07-14T16:11:12">
<testcase name="test01" classname="de.hsrm.sls.eva.junit.samples.simple.PingTest" time="0.005">
<system-out><![CDATA[JAA]]></system-out>
<system-err><![CDATA[BUUUUH]]></system-err>
<failure message="expected: <43> but was: <42>">java.lang.AssertionError: expected:&lt;43&gt; but was:&lt;42&gt;
at de.hsrm.sls.eva.junit.samples.simple.PingTest.test02(PingTest.java:23)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at de.hsrm.sls.eva.junit.Runner.runTests(Runner.java:28)
at de.hsrm.sls.eva.junit.Runner.main(Runner.java:18)
</failure>
</testcase>
<testcase name="test02" classname="de.hsrm.sls.eva.junit.samples.simple.PingTest" time="0.005">
<error message="Moin">java.lang.RuntimeException: Moin
at de.hsrm.sls.eva.junit.samples.simple.Ping.faulty(Ping.java:8)
at de.hsrm.sls.eva.junit.samples.simple.PingTest.test03(PingTest.java:28)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at de.hsrm.sls.eva.junit.Runner.runTests(Runner.java:28)
at de.hsrm.sls.eva.junit.Runner.main(Runner.java:18)
</error>
</testcase>
<testcase name="test03" classname="de.hsrm.sls.eva.junit.samples.simple.PingTest" time="0.005" />
<testcase name="test04" classname="de.hsrm.sls.eva.junit.samples.simple.PingTest">
<timeout timeout="3"/>
</testcase>
<system-out><![CDATA[JAA]]></system-out>
<system-err><![CDATA[BUUUUH]]></system-err>
<!-- ergibt hier wenig Sinn (da im Beispiel Java Testfälle gezeigt) - nur zur Veranschaulichung der Struktur-->
<storage allocated="2" free="1"/>
</testsuite>
info

Die Reihenfolge der Elemente ist egal.

Wurzelelement

AttributErforderlichTypBeschreibung
timestampneinISO8601Start (UTC)
timeneindoubleAusführungszeit in Sekunden wenn die Testsuite beendet wurde. Wird die Testausführung vorher abgebrochen, ist der Wert nicht gesetzt. Achtung: Der Wert entspricht nicht unbedingt der Summe der time-Attribute aus allen Testfällen. Der Overhead für die Ausführung der Testfälle kann signifikant höher sein als die Ausführung selbst.

Ergebnisse zu Testfällen

trex.xml
<testcase name="test01" classname="de.hsrm.sls.eva.junit.samples.simple.PingTest" time="0.005">
<system-out><![CDATA[JAA]]></system-out>
<system-err><![CDATA[BUUUUH]]></system-err>
<failure message="expected: <43> but was: <42>">java.lang.AssertionError: expected:&lt;43&gt; but was:&lt;42&gt;
at de.hsrm.sls.eva.junit.samples.simple.PingTest.test02(PingTest.java:23)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at de.hsrm.sls.eva.junit.Runner.runTests(Runner.java:28)
at de.hsrm.sls.eva.junit.Runner.main(Runner.java:18)
</failure>
</testcase>
AttributErforderlichTypBeschreibung
namejastringName des Testfalls
classnameneinstringName der Testklasse (bzw. Testdatei wenn Klasse nicht zutreffend ist)
timeneindoubleAusführungsdauer des Testfalls in Sekunden wenn der Testfall beendet wurde. Wenn ein Timeout auftritt, ist time nicht gesetzt.

Der Inhalt der testcase-Elemente (das Resultat) kann leer sein (Testfall erfolgreich) oder einer der folgenden Elemente enthalten:

  • error: Wenn der Testfall wegen eines Asserts fehlgeschlagen ist. Attribut message enthält den manuell gepflegten Assertion-Hinweis. Falls nicht vorhanden, muss eine generierte Beschreibung, also was erwartet und was vorhanden war, eingefügt werden
  • failure: Wenn der Testfall wegen einer Exception (die nicht erwartet wurde) fehlgeschlagen ist . Attribut message enthält einen kurzen Grund für die Exception
  • timeout: Wenn der Testfall nicht innerhalb einer angemessenen Zeit terminierte. Das Attribut timeout gibt an, wie lange auf ein Ergebnis gewartet wurde (in Sekunden).
  • pending: Wenn der Testfall noch nicht ausgeführt wurde
  • (started): Wenn der Testfall gestartet (aber noch nicht beendet) wurde. Dieses Element wird nur innerhalb von Eva verwendet und mit timeout ersetzt, bevor das Ergebnis an den Client gesendet wird.. Hintergrund: Aufgrund von technischen Limitierungen kann timeout nicht immer gesetzt werden. Wenn der Prozess der Testausführung abgeschossen wird, bestimmt Eva den zuletzt gestarteten Testfall (anhand des started-Elements) und ändert diesen automatisch zu timeout.

Die Elemente können (optional) weitere Details enthalten. Hinsichtlich der Details gibt es keine Vorgaben. Im Fall von Java könnte beispielsweise der Stack Trace der Exception enthalten sein, die das Resultat verursacht hat.

Zu jedem Testfall können (optional) system-out und system-err-Elemente mit den entsprechenden Ausgaben pro Testfall hinzugefügt werden. system-err sollten nicht mit Details zum Fehler befüllt werden, wenn es ein entsprechendes error bzw. failure Resultat gibt. Der Inhalt der system-out und system-err-Elemente müssen begrenzt werden, sodass es bei Endlosschleifen o.ä. zu keinen Dokumenten kommt, die mehrere Dutzend oder Hundert Megabyte groß sind. Derart große Dokumente führen zu Überläufen des verfügbaren Speichers und können nicht so einfach über das Netzwerk übertragen werden. Ein möglicher Richtwert wäre die Begrenzung auf 4096 Zeichen pro Element. Wird der Inhalt abgeschnitten, sollten die letzten N Zeichen der Ausgabe verwendet werden und es sollte gekennzeichnet werden, dass der Inhalt abgeschnitten wurde.

Speicher

In einigen Sprachen muss Speicher manuell allokiert und freigegeben werden. Die korrekte Nutzung von solchen Operationen (innerhalb des getesteten Codes) kann mit diesem Element (optional) aufgezeichnet werden.

trex.xml
<storage allocated="2", free="1"/>
AttributErforderlichTypBeschreibung
allocatedjaintAnzahl der ausgeführten Operationen, die Speicher allokieren (z.B. jeder Call von malloc())
freejaintAnzahl der ausgeführten Operationen, die Speicher freigeben

Standard/Fehlerausgaben

Zusätzlich zu den Ausgaben pro Testfall kann hier (optional) die aggregierte Ausgabe über alle Testfälle dargestellt werden.