web-dev-qa-db-fra.com

Quelle est la spécification de format XML JUnit prise en charge par Hudson?

J'ai Hudson comme serveur d'intégration continue et je souhaite utiliser l'option 'Publier le résultat du test JUnit'. Mais je n’utilise pas les outils xUnit pour les tests, au lieu de cela, j’ai des scripts Shell qui exécutent des tests et renvoient des résultats au format simple. Je pense faire un script qui transforme ces résultats au format JUnit. Je suis donc intéressant de savoir à quoi le fichier JUnit doit ressembler?

172
krvladislav

J'ai fait la même chose il y a quelques mois, et il s'est avéré que ce format simple était suffisant pour que Hudson l'accepte comme protocole de test:

<testsuite tests="3">
    <testcase classname="foo1" name="ASuccessfulTest"/>
    <testcase classname="foo2" name="AnotherSuccessfulTest"/>
    <testcase classname="foo3" name="AFailingTest">
        <failure type="NotEnoughFoo"> details about failure </failure>
    </testcase>
</testsuite>

Cette question a des réponses avec plus de détails: Spec. For JUnit XML Output

123
Anders Lindahl

Je viens de récupérer le junit-4.xsd auquel d'autres ont associé et utilisé un outil nommé XMLSpear pour convertir le schéma en un fichier XML vierge avec les options indiquées ci-dessous. Voici le résultat (légèrement nettoyé):

<?xml version="1.0" encoding="UTF-8"?>
<testsuites disabled="" errors="" failures="" name="" tests="" time="">
    <testsuite disabled="" errors="" failures="" hostname="" id=""
               name="" package="" skipped="" tests="" time="" timestamp="">
        <properties>
            <property name="" value=""/>
        </properties>
        <testcase assertions="" classname="" name="" status="" time="">
            <skipped/>
            <error message="" type=""/>
            <failure message="" type=""/>
            <system-out/>
            <system-err/>
        </testcase>
        <system-out/>
        <system-err/>
    </testsuite>
</testsuites>

Certains de ces éléments peuvent apparaître plusieurs fois:

  • Il ne peut y avoir qu'un seul élément testsuites, puisque c'est ainsi que XML fonctionne, mais il peut y avoir plusieurs éléments testsuite dans l'élément testsuites.
  • Chaque élément properties peut avoir plusieurs enfants property.
  • Chaque élément testsuite peut avoir plusieurs enfants testcase.
  • Chaque élément testcase peut avoir plusieurs enfants error, failure, system-out ou system-err.

XMLSpear options

85
Todd Mazierski

Le réponse du haut de la question Anders Lindahl fait référence à un fichier xsd .

Personnellement, j'ai trouvé ce fichier xsd également très utile (je ne me souviens pas comment j'ai trouvé celui-là). Cela semble un peu moins intimidant et, dans la mesure où je l'ai utilisé, tous les éléments et attributs semblent être reconnus par Jenkins (v1.451).

Une chose cependant: lors de l’ajout de plusieurs éléments <failure ..., un seul a été retenu dans Jenkins. Lors de la création du fichier XML, je concatène maintenant tous les échecs en un.


Mise à jour 2016-11 Le lien est cassé maintenant. Une meilleure alternative est cette page de cubic.org: format de fichier de rapport XML JUnit , où un effort de Nice a été fourni pour fournir un exemple sensible documenté . Exemple et xsd sont copiés ci-dessous, mais leur page a l’air plus agréable.


exemple de fichier XML JUnit

<?xml version="1.0" encoding="UTF-8"?>
<!-- a description of the JUnit XML format and how Jenkins parses it. See also junit.xsd -->

<!-- if only a single testsuite element is present, the testsuites
     element can be omitted. All attributes are optional. -->
<testsuites disabled="" <!-- total number of disabled tests from all testsuites. -->
            errors=""   <!-- total number of tests with error result from all testsuites. -->
            failures="" <!-- total number of failed tests from all testsuites. -->
            name=""
            tests=""    <!-- total number of successful tests from all testsuites. -->
            time=""     <!-- time in seconds to execute all test suites. -->
        >

  <!-- testsuite can appear multiple times, if contained in a testsuites element.
       It can also be the root element. -->
  <testsuite name=""      <!-- Full (class) name of the test for non-aggregated testsuite documents.
                               Class name without the package for aggregated testsuites documents. Required -->
         tests=""     <!-- The total number of tests in the suite, required. -->
         disabled=""  <!-- the total number of disabled tests in the suite. optional -->
             errors=""    <!-- The total number of tests in the suite that errored. An errored test is one that had an unanticipated problem,
                               for example an unchecked throwable; or a problem with the implementation of the test. optional -->
             failures=""  <!-- The total number of tests in the suite that failed. A failure is a test which the code has explicitly failed
                               by using the mechanisms for that purpose. e.g., via an assertEquals. optional -->
             hostname=""  <!-- Host on which the tests were executed. 'localhost' should be used if the hostname cannot be determined. optional -->
         id=""        <!-- Starts at 0 for the first testsuite and is incremented by 1 for each following testsuite -->
         package=""   <!-- Derived from testsuite/@name in the non-aggregated documents. optional -->
         skipped=""   <!-- The total number of skipped tests. optional -->
         time=""      <!-- Time taken (in seconds) to execute the tests in the suite. optional -->
         timestamp="" <!-- when the test was executed in ISO 8601 format (2014-01-21T16:17:18). Timezone may not be specified. optional -->
         >

    <!-- Properties (e.g., environment settings) set during test
     execution. The properties element can appear 0 or once. -->
    <properties>
      <!-- property can appear multiple times. The name and value attributres are required. -->
      <property name="" value=""/>
    </properties>

    <!-- testcase can appear multiple times, see /testsuites/testsuite@tests -->
    <testcase name=""       <!-- Name of the test method, required. -->
          assertions="" <!-- number of assertions in the test case. optional -->
          classname=""  <!-- Full class name for the class the test method is in. required -->
          status=""
          time=""       <!-- Time taken (in seconds) to execute the test. optional -->
          >

      <!-- If the test was not executed or failed, you can specify one
           the skipped, error or failure elements. -->

      <!-- skipped can appear 0 or once. optional -->
      <skipped/>

      <!-- Indicates that the test errored. An errored test is one
           that had an unanticipated problem. For example an unchecked
           throwable or a problem with the implementation of the
           test. Contains as a text node relevant data for the error,
           for example a stack trace. optional -->
      <error message="" <!-- The error message. e.g., if a Java exception is thrown, the return value of getMessage() -->
         type=""    <!-- The type of error that occured. e.g., if a Java execption is thrown the full class name of the exception. -->
         ></error>

      <!-- Indicates that the test failed. A failure is a test which
       the code has explicitly failed by using the mechanisms for
       that purpose. For example via an assertEquals. Contains as
       a text node relevant data for the failure, e.g., a stack
       trace. optional -->
      <failure message="" <!-- The message specified in the assert. -->
           type=""    <!-- The type of the assert. -->
           ></failure>

      <!-- Data that was written to standard out while the test was executed. optional -->
      <system-out></system-out>

      <!-- Data that was written to standard error while the test was executed. optional -->
      <system-err></system-err>
    </testcase>

    <!-- Data that was written to standard out while the test suite was executed. optional -->
    <system-out></system-out>
    <!-- Data that was written to standard error while the test suite was executed. optional -->
    <system-err></system-err>
  </testsuite>
</testsuites>

Fichier JUnit XSD

<?xml version="1.0" encoding="UTF-8" ?>
<!-- from https://svn.jenkins-ci.org/trunk/hudson/dtkit/dtkit-format/dtkit-junit-model/src/main/resources/com/thalesgroup/dtkit/junit/model/xsd/junit-4.xsd -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:element name="failure">
        <xs:complexType mixed="true">
            <xs:attribute name="type" type="xs:string" use="optional"/>
            <xs:attribute name="message" type="xs:string" use="optional"/>
        </xs:complexType>
    </xs:element>

    <xs:element name="error">
        <xs:complexType mixed="true">
            <xs:attribute name="type" type="xs:string" use="optional"/>
            <xs:attribute name="message" type="xs:string" use="optional"/>
        </xs:complexType>
    </xs:element>

    <xs:element name="properties">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="property" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="property">
        <xs:complexType>
            <xs:attribute name="name" type="xs:string" use="required"/>
            <xs:attribute name="value" type="xs:string" use="required"/>
        </xs:complexType>
    </xs:element>

    <xs:element name="skipped" type="xs:string"/>
    <xs:element name="system-err" type="xs:string"/>
    <xs:element name="system-out" type="xs:string"/>

    <xs:element name="testcase">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="skipped" minOccurs="0" maxOccurs="1"/>
                <xs:element ref="error" minOccurs="0" maxOccurs="unbounded"/>
                <xs:element ref="failure" minOccurs="0" maxOccurs="unbounded"/>
                <xs:element ref="system-out" minOccurs="0" maxOccurs="unbounded"/>
                <xs:element ref="system-err" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
            <xs:attribute name="name" type="xs:string" use="required"/>
            <xs:attribute name="assertions" type="xs:string" use="optional"/>
            <xs:attribute name="time" type="xs:string" use="optional"/>
            <xs:attribute name="classname" type="xs:string" use="optional"/>
            <xs:attribute name="status" type="xs:string" use="optional"/>
        </xs:complexType>
    </xs:element>

    <xs:element name="testsuite">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="properties" minOccurs="0" maxOccurs="1"/>
                <xs:element ref="testcase" minOccurs="0" maxOccurs="unbounded"/>
                <xs:element ref="system-out" minOccurs="0" maxOccurs="1"/>
                <xs:element ref="system-err" minOccurs="0" maxOccurs="1"/>
            </xs:sequence>
            <xs:attribute name="name" type="xs:string" use="required"/>
            <xs:attribute name="tests" type="xs:string" use="required"/>
            <xs:attribute name="failures" type="xs:string" use="optional"/>
            <xs:attribute name="errors" type="xs:string" use="optional"/>
            <xs:attribute name="time" type="xs:string" use="optional"/>
            <xs:attribute name="disabled" type="xs:string" use="optional"/>
            <xs:attribute name="skipped" type="xs:string" use="optional"/>
            <xs:attribute name="timestamp" type="xs:string" use="optional"/>
            <xs:attribute name="hostname" type="xs:string" use="optional"/>
            <xs:attribute name="id" type="xs:string" use="optional"/>
            <xs:attribute name="package" type="xs:string" use="optional"/>
        </xs:complexType>
    </xs:element>

    <xs:element name="testsuites">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="testsuite" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
            <xs:attribute name="name" type="xs:string" use="optional"/>
            <xs:attribute name="time" type="xs:string" use="optional"/>
            <xs:attribute name="tests" type="xs:string" use="optional"/>
            <xs:attribute name="failures" type="xs:string" use="optional"/>
            <xs:attribute name="disabled" type="xs:string" use="optional"/>
            <xs:attribute name="errors" type="xs:string" use="optional"/>
        </xs:complexType>
    </xs:element>

</xs:schema>
37
parvus

Je ne pouvais pas trouver de bonne information à ce sujet, alors j'ai fait quelques essais et erreurs. Les attributs et champs suivants (et uniquement ceux-ci) sont reconnus par Jenkins (v1.585).

<?xml version="1.0" encoding="UTF-8"?>
<testsuite>

  <!-- if your classname does not include a dot, the package defaults to "(root)" -->
  <testcase name="my testcase" classname="my package.my classname" time="29">

    <!-- If the test didn't pass, specify ONE of the following 3 cases -->

    <!-- option 1 --> <skipped />
    <!-- option 2 --> <failure message="my failure message">my stack trace</failure>
    <!-- option 3 --> <error message="my error message">my crash report</error>

    <system-out>my STDOUT dump</system-out>

    <system-err>my STDERR dump</system-err>

  </testcase>

</testsuite>

(J'ai commencé avec cet exemple de document XML et j'ai travaillé à partir de là.)

25
Ian

Structure de base Voici un exemple de fichier de sortie JUnit, montrant un résultat d’omission et d’échec, ainsi qu’un seul résultat transmis.

<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
   <testsuite name="JUnitXmlReporter" errors="0" tests="0" failures="0" time="0" timestamp="2013-05-24T10:23:58" />
   <testsuite name="JUnitXmlReporter.constructor" errors="0" skipped="1" tests="3" failures="1" time="0.006" timestamp="2013-05-24T10:23:58">
      <properties>
         <property name="Java.vendor" value="Sun Microsystems Inc." />
         <property name="compiler.debug" value="on" />
         <property name="project.jdk.classpath" value="jdk.classpath.1.6" />
      </properties>
      <testcase classname="JUnitXmlReporter.constructor" name="should default path to an empty string" time="0.006">
         <failure message="test failure">Assertion failed</failure>
      </testcase>
      <testcase classname="JUnitXmlReporter.constructor" name="should default consolidate to true" time="0">
         <skipped />
      </testcase>
      <testcase classname="JUnitXmlReporter.constructor" name="should default useDotNotation to true" time="0" />
   </testsuite>
</testsuites>

Vous trouverez ci-dessous la structure documentée d'un rapport XML JUnit typique. Notez qu'un rapport peut contenir une ou plusieurs suites de tests. Chaque suite de tests possède un ensemble de propriétés (informations d’enregistrement d’enregistrement). Chaque suite de tests contient également un ou plusieurs scénarios de test et chaque scénario de test contient un noeud ignoré, en cas d'échec ou d'erreur si le test n'a pas abouti. Si le scénario de test est réussi, il ne contiendra aucun nœud. Pour plus de détails sur les attributs valides pour chaque noeud, veuillez consulter la section suivante "Schéma".

<testsuites>        => the aggregated result of all junit testfiles
  <testsuite>       => the output from a single TestSuite
    <properties>    => the defined properties at test execution
      <property>    => name/value pair for a single property
      ...
    </properties>
    <error></error> => optional information, in place of a test case - normally if the tests in the suite could not be found etc.
    <testcase>      => the results from executing a test method
      <system-out>  => data written to System.out during the test run
      <system-err>  => data written to System.err during the test run
      <skipped/>    => test was skipped
      <failure>     => test failed
      <error>       => test encountered an error
    </testcase>
    ...
  </testsuite>
  ...
</testsuites>
6

Il existe plusieurs schémas pour les résultats "JUnit" et "xUnit".

Veuillez noter que Jenkins xunit-plugin utilise plusieurs versions du schéma (la dernière version en date est junit-10.xsd, ce qui permet de prendre en charge le format Erlang/OTP Junit).

Certains frameworks de test, ainsi que les plugins de reporting de style "xUnit", utilisent également leur propre sauce secrète pour générer des rapports de style "xUnit", ceux-ci ne peuvent pas utiliser un schéma particulier (veuillez lire: ils essaient de mais les outils ne peuvent pas valider un schéma). Python unittests dans Jenkins? donne une comparaison rapide de plusieurs de ces bibliothèques et de légères différences entre les rapports xml générés.

4
dnozay

J'ai décidé de poster une nouvelle réponse, car certaines réponses existantes sont obsolètes ou incomplètes.

Tout d'abord: rien ne ressemble à JUnit XML Format Specification, simplement parce que JUnit ne produit aucun type de rapport XML ou HTML.

La génération de rapports XML elle-même provient de la tâche Ant JUnit/Maven Surefire Plugin/Gradle (selon votre choix pour l'exécution de vos tests). Le format de rapport XML a été introduit pour la première fois par Ant et ensuite adapté par Maven (et Gradle).

Si quelqu'un a juste besoin d'un format XML officiel, alors:

  1. Il existe un schéma pour un rapport XML généré par maven surefire et il peut être trouvé ici: surefire-test-report.xsd .
  2. Pour un fichier XML généré par ant, un schéma tiers est disponible ici (mais il peut être légèrement obsolète).

J'espère que ça va aider quelqu'un.

2
G. Demecki

Bonnes réponses ici sur l'utilisation de python: (il y a plusieurs façons de le faire) Python unittests dans Jenkins?

IMHO le meilleur moyen est écrire python unittest tests et installer pytest (quelque chose comme 'yum install pytest') pour installer py.test. Puis exécutez des tests comme celui-ci: 'py.test --junitxml results.xml test.py' . Vous pouvez exécuter n'importe quel script unittest python et obtenir les résultats XML jUnit.

https://docs.python.org/2.7/library/unittest.html

Dans la configuration de génération de jenkins Actions de post-génération Ajoutez une action "Publier le résultat du test JUnit" avec result.xml et tous les autres fichiers de résultats de test que vous produisez.

1
gaoithe