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
-Elementsystem-out
undsystem-err
Elemente protestcase
(bereits in anderen Tools genutzt)pending
undstarted
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
<?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:<43> but was:<42>
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>
Die Reihenfolge der Elemente ist egal.
Wurzelelement
Attribut | Erforderlich | Typ | Beschreibung |
---|---|---|---|
timestamp | nein | ISO8601 | Start (UTC) |
time | nein | double | Ausfü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
<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:<43> but was:<42>
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>
Attribut | Erforderlich | Typ | Beschreibung |
---|---|---|---|
name | ja | string | Name des Testfalls |
classname | nein | string | Name der Testklasse (bzw. Testdatei wenn Klasse nicht zutreffend ist) |
time | nein | double | Ausfü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. Attributmessage
enthält den manuell gepflegten Assertion-Hinweis. Falls nicht vorhanden, muss eine generierte Beschreibung, also was erwartet und was vorhanden war, eingefügt werdenfailure
: Wenn der Testfall wegen einer Exception (die nicht erwartet wurde) fehlgeschlagen ist . Attributmessage
enthält einen kurzen Grund für die Exceptiontimeout
: Wenn der Testfall nicht innerhalb einer angemessenen Zeit terminierte. Das Attributtimeout
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 mittimeout
ersetzt, bevor das Ergebnis an den Client gesendet wird.. Hintergrund: Aufgrund von technischen Limitierungen kanntimeout
nicht immer gesetzt werden. Wenn der Prozess der Testausführung abgeschossen wird, bestimmt Eva den zuletzt gestarteten Testfall (anhand desstarted
-Elements) und ändert diesen automatisch zutimeout
.
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.
<storage allocated="2", free="1"/>
Attribut | Erforderlich | Typ | Beschreibung |
---|---|---|---|
allocated | ja | int | Anzahl der ausgeführten Operationen, die Speicher allokieren (z.B. jeder Call von malloc() ) |
free | ja | int | Anzahl 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.