Hudson이 지원하는 JUnit XML 형식 사양은 무엇입니까?


183

연속 통합 서버로 Hudson을 사용하고 있으며 'Publish JUnit 테스트 결과 보고서'옵션을 사용하고 싶습니다. 그러나 테스트를 위해 xUnit 도구를 사용하지 않습니다. 대신 테스트를 실행하고 간단한 형식으로 결과를 반환하는 쉘 스크립트가 있습니다. 이 결과를 JUnit 형식으로 변환하는 스크립트를 작성하려고합니다. JUnit 파일이 어떻게 보이는지 흥미 롭습니다.


JUnit을 사용하지 않는 이유는 무엇입니까? 이러한 테스트는 다양한 도구 cmd, UI 등을 통해 다양한 방식으로 자동화 될 수 있습니다.
Aaron McIver

6
@AaronMcIver : 셸 스크립트는 Java가 아닌 언어에서 테스트를 실행하는 데 매우 적합합니다. JUnit을 어떻게 사용 하시겠습니까?
벤 Voigt

1
@ BenVoigt 처음에는 OP에 Java가 포함되어 있다고 가정하고 테스트 장치로 JUnit을 우회하려고했습니다. 질문을 검토 한 후에는 그렇지 않습니다. 나타납니다 code.google.com/p/shell2junit이 두번째보기 후 영업 이익을 일부 사용을 제공 할 수 있습니다.
Aaron McIver

1
shell2unit 라인을 따라 여기에 JUnit XML을 구문 분석 / 출력 할 수있는 JAXB 클래스가 있습니다. gist.github.com/agentgt/8583649
Adam Gent

답변:


127

나는 몇 달 전에 비슷한 일을했으며,이 간단한 형식으로 허드슨이 테스트 프로토콜로 받아 들일 수있는 것으로 나타났습니다.

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

이 질문에는 더 자세한 내용이 있습니다 : 사양. JUnit XML 출력용


xunit 플러그인은 'classname'속성을 거부하고 'class'만 허용
하므로이

10
나는 반대의 문제가 있었다. class거부되었고 만 classname작동했습니다.
ryanbrainard

1
xUnit 플러그인을 1.60으로 업그레이드했을 때 실패했습니다. 유효성 검사기가 더 엄격 해짐에 따라 <testsuite tests="(number of tests)">ex 를 추가해야했습니다 . <testsuite tests="10">.
Kevin Brotcke

2
@KevinBrotcke에게 감사드립니다. 해당 속성을 포함하도록 답변을 업데이트하겠습니다.
Anders Lindahl 2016 년

2
또한 Hudson이 패키지 / 스위트별로 테스트를 구성하게하려면 classname 속성에 패키지를 지정해야합니다. 예 : <testcase classname="foo.bar" name="ATest" /> Jenkins의 foo 패키지에 bar 클래스를 배치하여 테스트 모음을보다 체계적으로 만듭니다.
jluzwick

90

방금 다른 사람들이 XMLSpear 라는 도구에 링크 하고 스키마를 빈 XML 파일로 변환하기 위해 아래에 표시된 옵션을 사용 하여 junit-4.xsd가져 왔습니다 . 이것은 (약간 정리 된) 결과입니다.

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

이러한 항목 중 일부는 여러 번 나타날 수 있습니다.

  • testsuitesXML이 작동하는 방식이므로 하나의 요소 만있을 수 있지만 testsuite요소 내에 여러 요소 가있을 수 있습니다 testsuites.
  • properties요소는 여러 개의 property하위를 가질 수 있습니다 .
  • testsuite요소는 여러 개의 testcase하위를 가질 수 있습니다 .
  • testcase요소는 여러 가질 수 error, failure, system-out, 또는 system-err아이들.

XMLSpear 옵션


1
테스트 케이스의 상태 또는 오류 유형과 같은 특정 속성의 유효한 값을 설명하는 문서가 있습니까?
Eric Cope

1
@EricCope 소스 코드 svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/…를 살펴 보는 것이 좋습니다 . 기본적으로 그것은 단지 문자열입니다.
Sulthan

4
태그가 중복되는 이유는 무엇입니까?
Nakilon

설정 미러 : imgur.com/quneFJf alt : Rootelement: testsuites, Max recursive de...: 2, Max Repeat factor: 2, include optional elements: (예 = 틱), include optional attributes: (예 = 틱)
n611x007

1
@Nakilon 그것은 2.5 년 늦었지만 그것을
고쳤

45

질문 Anders Lindahl최상위 답변xsd 파일을 나타냅니다 .

개인적 으로이 xsd 파일 도 매우 유용하다는 것을 알았습니다 (어떻게 찾았는지 기억하지 못합니다). 조금 덜 위협적으로 보이며 사용했던 한 모든 요소와 속성이 Jenkins (v1.451)에 의해 인식되는 것처럼 보입니다.

그러나 한 가지 : 여러 <failure ...요소를 추가 할 때 Jenkins에는 하나만 유지되었습니다. xml 파일을 만들 때 모든 실패를 하나로 연결합니다.


2016-11 업데이트 링크가 끊어졌습니다. 더 나은 대안은 cubic.org : JUnit XML보고 파일 형식 의이 페이지 입니다 . 여기에서 합리적인 문서화 된 예제 를 제공하기 위해 많은 노력을 기울였습니다 . 예제와 xsd가 아래에 복사되었지만 페이지가 더 멋지게 보입니다.


샘플 JUnit XML 파일

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

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

실패하면 어떻게 멋지게 보이나요? 줄 바꿈 문자를 수동으로 추가하고 싶지만 Jenkins에는 표시되지 않습니다.
rationalcoder

그것은 내 접근 방식의 단점입니다. 나는 그 우물로 고군분투했던 것을 기억합니다. & lt; br / & gt;와 같은 것을 추가하십시오. -이것이 어떻게 해결되었는지 잊어 버렸습니다 (그리고 우리는 이것을 더 이상 사용하지 않습니다). 그러나 이것은 시도할만한 가치가있는 것 같습니다.
parvus

1
나는 그 주위에 길을 찾았습니다. c ++를 사용하고 있기 때문에 실패 메시지에서 실패 횟수를보고하고 "스택 추적"을 사용하여 실제 실패를보고합니다. 스택 추적은 failure 요소의 본문이있는 텍스트에서보고되므로 새 행이 올바르게 지원됩니다.
rationalcoder

25

나는 이것에 대한 좋은 정보를 찾을 수 없었기 때문에 시행 착오를 겪었다. 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>

( 이 샘플 XML 문서로 시작하여 거꾸로 작업했습니다.)


6

기본 구조 다음은 건너 뛰기 및 실패한 결과와 하나의 전달 된 결과를 표시하는 JUnit 출력 파일의 예입니다.

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

다음은 일반적인 JUnit XML 보고서의 문서화 된 구조입니다. 보고서에는 하나 이상의 테스트 스위트가 포함될 수 있습니다. 각 테스트 스위트에는 일련의 속성 (레코딩 환경 정보)이 있습니다. 각 테스트 스위트에는 하나 이상의 테스트 케이스가 포함되어 있으며 테스트에 통과하지 못한 경우 각 테스트 케이스에는 건너 뛰기, 실패 또는 오류 노드가 포함됩니다. 테스트 사례가 통과 한 경우 노드가 포함되지 않습니다. 각 노드에 유효한 속성에 대한 자세한 내용은 다음 "스키마"섹션을 참조하십시오.

<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"및 "xUnit"결과에 대한 여러 스키마가 있습니다.

Jenkins xunit-plugin에서 사용중인 여러 버전의 스키마가 있습니다 (현재 최신 버전은 junit-10.xsdErlang / OTP Junit 형식에 대한 지원을 추가 함).

"xUnit"스타일보고 플러그인뿐만 아니라 일부 테스트 프레임 워크는 고유 한 비밀 소스를 사용하여 "xUnit"스타일 보고서를 생성합니다. 이러한 스키마는 특정 스키마를 사용하지 않을 수 있습니다 (읽어보십시오. 그러나 도구는 검증되지 않습니다) 하나의 스키마). 젠킨스에서 파이썬 단위 테스트? 이러한 라이브러리 중 몇 가지를 빠르게 비교하고 생성 된 xml 보고서간에 약간의 차이가 있습니다.


2

파이썬 사용에 대한 좋은 대답 : 젠킨스에서 파이썬 단위 테스트 는 (여러 가지 방법이 있습니다) ?

가장 좋은 방법은 파이썬 unittest 테스트를 작성 하고 pytest ( 'yum install pytest'와 같은)를 설치하여 py.test를 설치하는 것입니다. 그런 다음 'py.test --junitxml results.xml test.py'와 같은 테스트를 실행하십시오 . unittest python 스크립트를 실행하고 jUnit xml 결과를 얻을 수 있습니다.

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

jenkins 빌드 구성에서 빌드 후 조치 result.xml 및 더 많은 테스트 결과 파일이 포함 된 "Publish JUnit 테스트 결과 보고서"조치를 추가하십시오.


2

기존 답변이 오래되었거나 불완전하기 때문에 새 답변을 게시하기로 결정했습니다.

우선 : JUnit XML Format SpecificationJUnit은 어떤 종류의 XML 또는 HTML 보고서도 생성하지 않기 때문에 이와 같은 것은 없습니다.

XML 보고서 생성 자체는 Ant JUnit 태스크 / Maven Surefire Plugin / Gradle (테스트 실행에 사용)에서 제공됩니다. XML 보고서 형식은 Ant에 의해 처음 소개되었고 나중에 Maven (및 Gradle)에 의해 수정되었습니다.

누군가 공식 XML 형식이 필요한 경우 :

  1. 거기에 받는다는 확실한 생성 된 XML 보고서에 대한 스키마가 존재하며 여기에서 찾을 수 있습니다 : 확실한 테스트 - report.xsd .
  2. 개미 생성 XML의 경우 여기에 사용 가능한 타사 스키마 가 있지만 약간 오래된 것일 수 있습니다.

누군가에게 도움이되기를 바랍니다.


설명해 주셔서 감사합니다. 오래된 Jenkins 1.6 인스턴스에서 Slack으로 JUnit 테스트 요약보내 려고합니다 . 이러한 XML 파일을 어디에 배치합니까?
JJD

@JJD 죄송합니다. 연락이 없습니다. 그러한 XML 파일 이 정확히 무엇을 의미 합니까? 하지만 이미 ant / maven / gradle로 JUnit 테스트를 실행한다고 가정합니다. 그렇다면이 도구는 테스트 실행 후 멋진 요약 보고서를 생성합니다. 젠킨스 버전은 여기서 중요하지 않습니다.
G. Demecki

예, 내 빌드는 Gradle을 통해 실행됩니다. Jenkins 1.6을 사용하는 동안 Slack 채널에 JUnit 테스트 요약을 보내고 싶습니다. GitHub 토론을 읽고 슬랙 플러그인이 테스트 요약을 선택할 수 있도록 구성 XML 파일을 어딘가에 배치해야한다고 생각했습니다. 어쩌면 내가 오해했을 수도 있습니다.
JJD

1
Gradle이 JUnit 테스트 시작을 완료 한 후 올바르게 생성 된 테스트 보고서가 있는지 확인하십시오. 그런 다음 Slack 플러그인이이 보고서를 사용할 수 있어야합니다.
G. Demecki

1
마지막으로 귀하의 조언이 올바른 방향으로 나아갔습니다 . XML 파일을 찾을 올바른 경로를 구성해야했습니다 . 내를 들어 안드로이드 와 프로젝트 여러 Gradle을 제품의 맛 , 작품을 다음과 같습니다 **/build/test-results/**/TEST-*.xml. 대단히 감사합니다 !!!
JJD
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.