Hudson'ın desteklediği JUnit XML formatı belirtimi nedir?


183

Hudson'ın sürekli entegrasyon sunucusu olarak var ve 'JUnit test sonucu raporunu yayınla' seçeneğini kullanmak istiyorum. Ama testler için xUnit araçları kullanmıyorum, bunun yerine testleri çalıştıran ve sonuçları basit biçimde döndüren kabuk komut dosyalarına sahibim. Bu sonuçları JUnit biçimine dönüştüren bir komut dosyası yapmayı düşünüyorum. JUnit dosyasının nasıl görünmesi gerektiği konusunda ilginç miyim?


JUnit kullanmamak için herhangi bir sebep var mı? Bu testler, çeşitli araçlar cmd, UI,
vb.İle

6
@AaronMcIver: Kabuk komut dosyaları, testleri (Java olmayan bir dilde) çalıştırmada oldukça iyidir. Bunun için JUnit'i nasıl kullanırsınız?
Ben Voigt

1
@BenVoigt Başlangıçta OP'nin Java'nın dahil olduğunu ve test koşum takımı olarak JUnit'i atlamak istediğini varsaymıştım. Soruyu inceledikten sonra bu büyük olasılıkla geçerli değildir. Anlaşılmaktadır code.google.com/p/shell2junit ikinci baktıktan sonra OP bazı kullanımını sağlayabilir.
Aaron McIver

1
Burada shell2unit çizgileri boyunca JUnit XML'i ayrıştırabilen / çıktılayabilen bir JAXB sınıfı var: gist.github.com/agentgt/8583649
Adam Gent

Yanıtlar:


127

Birkaç ay önce benzer bir şey yaptım ve Hudson'ın bunu bir test protokolü olarak kabul etmesi için bu basit formatın yeterli olduğu ortaya çıktı:

<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>

Bu sorunun daha fazla ayrıntı ile cevapları var: Spec. JUnit XML Çıkışı için


Lütfen bu yanıtı düzeltin, çünkü xunit eklentisi 'classname' özniteliğini reddeder ve yalnızca 'class' kabul eder
andho

10
tam tersi bir sorunum vardı. classreddedildi ve sadece classnameçalıştı.
ryanbrainard

1
XUnit eklentisini 1.60'a yükselttiğimde bu benim için başarısız olmaya başladı. Doğrulayıcının daha katı hale geldiğini ve <testsuite tests="(number of tests)">eski. <testsuite tests="10">.
Kevin Brotcke

2
Teşekkürler @ KevinBrotcke, bu özelliği eklemek için cevabı güncelleyeceğim.
Anders Lindahl

2
Ayrıca Hudson'ın testlerinizi pakete / pakete göre düzenlemesini sağlamak için classname özelliğinde bir paket belirtmeniz gerektiğini unutmayın. Örn: <testcase classname="foo.bar" name="ATest" /> Bu, bar sınıfını Jenkins'deki foo paketine koyar ve test koleksiyonunuzu daha organize hale getirir.
jluzwick

90

Sadece diğerlerinin bağlı olduğu junit-4.xsd yakaladı ve şema aşağıda gösterilen seçeneklerle boş bir XML dosyasına dönüştürmek için XMLSpear adlı bir araç kullandım . Bu (hafifçe temizlenmiş) sonuçtur:

<?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>

Bu öğelerin bazıları birden çok kez ortaya çıkabilir:

  • Yalnızca bir testsuitesöğe olabilir, çünkü XML böyle çalışır, ancak testsuiteöğe içinde birden çok öğe olabilir testsuites.
  • Her propertiesöğenin birden fazla propertyçocuğu olabilir.
  • Her testsuiteöğenin birden fazla testcaseçocuğu olabilir.
  • Her testcaseöğe birden sahip olabilir error, failure, system-out, veya system-errçocukları.

XMLSpear seçenekleri


1
Test çantasının durumu veya hatanın türü gibi belirli özelliklerin geçerli değerlerini açıklayan bir belge var mı?
Eric Cope

1
@EricCope svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/… kaynak koduna bakmanızı tavsiye ederim . Temelde sadece bir ip.
Sulthan

4
Etiketler neden kopyalanıyor?
Nakilon

ayarları ayna: imgur.com/quneFJf alt: Rootelement: testsuites, Max recursive de...: 2, Max Repeat factor: 2, include optional elements: (evet = işaretli), include optional attributes(evet = işaretli)
n611x007

1
@Nakilon 2.5 yıl gecikti, ama düzelttim
bdesham

45

Üst cevap soru Anders Lindahl bir atıfta xsd dosyası .

Şahsen bu xsd dosyasını da çok kullanışlı buldum (bunu nasıl bulduğumu hatırlamıyorum). Biraz daha az korkutucu görünüyor ve kullandığım kadarıyla, tüm öğeler ve nitelikler Jenkins tarafından tanınmış gibi görünüyor (v1.451)

Yine de bir şey: birden fazla <failure ...eleman eklerken Jenkins'de sadece bir tane tutuldu. Xml dosyasını oluştururken, şimdi tüm hataları birde birleştiriyorum.


Güncelleme 2016-11 Bağlantı şimdi kesildi. : Daha iyi bir alternatif cubic.org bu sayfası JUnit XML raporlama dosya biçimi , güzel bir çaba mantıklı sağlamak için alınmıştır belgelenmiş örnek. Örnek ve xsd aşağıda kopyalanmıştır, ancak sayfaları daha iyi görünür.


örnek JUnit XML dosyası

<?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>

JUnit XSD dosyası

<?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>

O zaman güzel görünme başarısızlıklarını nasıl elde edersiniz? Elle yeni satır karakterleri eklemek istiyorum ancak Jenkins'te görünmüyorlar.
rationalcoder

Bu benim yaklaşımımda bir dezavantaj. Bununla iyi mücadele ettiğini hatırlıyorum. & Lt; br / & gt; gibi bir şey eklemeye çalışın. - Bunun nasıl çözüldüğünü unuttum (ve artık kullanmıyoruz), ama bu denemeye değer bir şey gibi görünüyor.
parvus

1
Etrafında bir yol buldum. C ++ kullandığımız için sadece hata mesajındaki hataların sayısını bildiriyorum ve gerçek hataları rapor etmek için "Yığın İzleme" yi kullanıyorum. Yığın izi, hata öğesinin gövdesiyle birlikte gelen metinden bildirildiğinden, yeni satırlar doğru şekilde desteklenir.
rationalcoder

25

Bu konuda iyi bir bilgi bulamadım, bu yüzden biraz deneme yanılma yaptım. Aşağıdaki öznitelikler ve alanlar (ve yalnızca bunlar) Jenkins (v1.585) tarafından tanınır.

<?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>

( Bu örnek XML belgesiyle başladım ve oradan geriye doğru çalıştım.)


6

Temel Yapı Burada, bir atlama ve başarısız sonuç ile birlikte tek bir geçirilen sonuç gösteren bir JUnit çıktı dosyası örneği verilmiştir.

<?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>

Aşağıda, tipik bir JUnit XML raporunun belgelenmiş yapısı verilmiştir. Bir raporun 1 veya daha fazla test paketi içerebileceğine dikkat edin. Her test takımının bir dizi özelliği vardır (kayıt ortamı bilgileri). Her test paketi ayrıca 1 veya daha fazla test durumu içerir ve test geçmediyse her test durumu atlanmış, hata veya hata düğümü içerir. Test senaryosu geçtiyse, herhangi bir düğüm içermez. Her bir düğüm için hangi özniteliklerin geçerli olduğu hakkında daha fazla ayrıntı için lütfen aşağıdaki "Şema" bölümüne bakın.

<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>

4

"JUnit" ve "xUnit" sonuçları için birden fazla şema vardır.

Jenkins xunit-eklentisi tarafından kullanılan şemanın çeşitli sürümleri olduğunu lütfen unutmayın (en son sürüm junit-10.xsdErlang / OTP Junit formatı için destek ekler).

Bazı test çerçeveleri ve "xUnit" tarzı raporlama eklentileri de "xUnit" tarzı raporlar oluşturmak için kendi gizli soslarını kullanırlar, bunlar belirli bir şema kullanamayabilirler (lütfen okuyun: deniyorlar ancak araçlar herhangi birine karşı geçerli olmayabilir bir şema). Jenkins Python birim testleri? bu kütüphanelerin birkaçının hızlı bir şekilde karşılaştırılmasını ve oluşturulan xml raporları arasındaki ufak farklılıkları verir.


2

Burada python kullanımı ile ilgili iyi cevaplar: (bunu yapmanın birçok yolu vardır) Jenkins Python birim testleri?

IMHO en iyi yolu python unittest testleri yazmak ve py.test yüklü almak için pytest ('yum install pytest' gibi bir şey) yüklemek. Sonra şöyle testler yapın: 'py.test --junitxml results.xml test.py' . Herhangi bir unittest python betiğini çalıştırabilir ve jUnit xml sonuçları alabilirsiniz.

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

Jenkins build configuration Derleme sonrası eylemler results.xml ve ürettiğiniz diğer test sonucu dosyalarıyla bir "JUnit test sonucu raporu yayınla" eylemi ekleyin.


2

Yeni bir cevap göndermeye karar verdim, çünkü mevcut bazı cevaplar güncel değil veya eksik.

Her şeyden önce: JUnit XML Format SpecificationJUnit herhangi bir XML veya HTML raporu üretmediği için böyle bir şey yoktur .

XML rapor oluşturmanın kendisi Ant JUnit görevinden / Maven Surefire Plugin / Gradle'dan (testlerinizi çalıştırmak için hangisini kullanırsanız kullanın) gelir. XML rapor formatı önce Ant tarafından tanıtıldı ve daha sonra Maven (ve Gradle) tarafından uyarlandı.

Birinin sadece resmi bir XML formatına ihtiyacı varsa:

  1. Bir maven güzelliğinde üretilen XML raporu için bir şema vardır ve burada bulunabilir: surefire-test-report.xsd .
  2. Bir karınca oluşturulan XML için kullanılabilir 3. taraf şema vardır burada (ama biraz eski olabilir).

Umarım birine yardım eder.


Açıklık getirdiğiniz için teşekkürler. Eski bir Jenkins 1.6 örneğinden Slack için JUnit test özetleri göndermeye çalışıyorum - belki yardım? Böyle bir XML dosyasını nereye yerleştiririm?
JJD

@JJD Üzgünüm, seni anlamıyorum. Böyle bir XML dosyası ile tam olarak ne demek istiyorsun ? Ama JUnit testlerinizi ant / maven / gradle ile zaten yaptığınızı varsayıyorum, değil mi? Evetse, bu araçlar, testlerin yürütülmesinden sonra güzel özet raporu oluşturur. Jenkins'in versiyonu burada önemli değil.
G. Demecki

Evet, yapım Gradle üzerinden çalışıyor. Jenkins 1.6 kullanırken Slack kanalına bir JUnit test özeti göndermek istiyorum. GitHub tartışmasını okumak Slack eklentisinin test özetini almasına izin vermek için bir yere bir XML dosyası koymam gerektiğini düşündüm. Belki yanlış anlarım.
JJD

1
Lütfen Gradle JUnit testlerinizi başlattıktan sonra doğru şekilde oluşturulmuş test raporlarının mevcut olduğunu kontrol edin. Sonra Slack eklentisi bu raporları kullanabilmelidir.
G. Demecki

1
Sonunda, tavsiyeniz beni doğru yöne itti: XML dosyalarını aramak için doğru yolu yapılandırmam gerekiyordu . Benim İçin Android projeye birden Gradle ürün tatlar , eserlerini şu: **/build/test-results/**/TEST-*.xml. Çok teşekkür ederim!!!
JJD
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.