我将Hudson作为持续集成服务器,并且我想使用选项“发布JUnit测试结果报告”。但是我不使用xUnit工具进行测试,相反,我有运行测试并以简单格式返回结果的shell脚本。我正在考虑制作一个脚本,将这些结果转换为JUnit格式。所以我很有趣JUnit文件的外观如何?
我将Hudson作为持续集成服务器,并且我想使用选项“发布JUnit测试结果报告”。但是我不使用xUnit工具进行测试,相反,我有运行测试并以简单格式返回结果的shell脚本。我正在考虑制作一个脚本,将这些结果转换为JUnit格式。所以我很有趣JUnit文件的外观如何?
Answers:
几个月前,我做过类似的事情,结果证明这种简单的格式足以让哈德森接受它作为测试协议:
<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输出
class被拒绝了,只能classname奏效。
                    <testsuite tests="(number of tests)">ex。<testsuite tests="10">。
                    <testcase classname="foo.bar" name="ATest" />  这会将bar类放在Jenkins的foo包中,使您的测试集合更有条理。
                    我只是抓住了其他人链接到的junit-4.xsd,并使用了一个名为XMLSpear的工具,使用以下所示的选项将架构转换为空白XML文件。这是(稍作清理)的结果:
<?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>
其中一些项目可能会多次出现:
testsuites因为XML是这样工作的,所以只能有一个元素,但是testsuite元素内可以有多个元素testsuites。properties元素可以有多个property子代。testsuite元素可以有多个testcase子代。testcase元素可以有多个error,failure,system-out,或system-err孩子。Rootelement,testsuites:Max recursive de...,2:Max Repeat factor,2:(include optional elements是=打勾)include optional attributes:(是=打勾)
                    我个人觉得这个xsd文件也非常有用(我不记得自己是怎么找到的)。看起来没那么吓人,就我所使用的而言,Jenkins(v1.451)似乎可以识别所有元素和属性。
但是,有一件事:在添加多个<failure ...元素时,詹金斯只保留了一个元素。现在,在创建xml文件时,我将所有失败串联在一起。
更新2016-11链接现在已断开。更好的替代方法是cubic.org的以下页面:JUnit XML报告文件格式,在此页面上我们竭尽全力提供了一个合理的文档示例。示例和xsd复制到下面,但是它们的页面看起来更好。
<?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>
<?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(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文档开始,然后从那里开始。)
基本结构这是一个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报表的文档结构。请注意,一个报告可以包含1个或多个测试套件。每个测试套件都有一组属性(记录环境信息)。每个测试套件还包含一个或多个测试用例,如果测试未通过,则每个测试用例将包含跳过,失败或错误节点。如果测试用例通过,则它将不包含任何节点。有关每个节点有效的属性的更多详细信息,请参阅以下“模式”部分。
<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>
              “ JUnit”和“ xUnit”结果有多个模式。
model/xsd)请注意,Jenkins xunit-plugin使用的模式有多个版本(当前的最新版本junit-10.xsd添加了对Erlang / OTP Junit格式的支持)。
一些测试框架以及“ xUnit”风格的报告插件也使用它们自己的秘密工具来生成“ xUnit”风格的报告,这些报告可能未使用特定的架构(请阅读:他们试图这样做,但这些工具可能无法针对任何形式进行验证一种模式)。Jenkins中的Python单元测试?可以快速比较其中的几个库,并在生成的xml报告之间略有不同。
关于使用python的良好答案:(有很多方法可以使用) Jenkins中的Python单元测试?
恕我直言,最好的方法是编写python 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以及您生成的更多测试结果文件的“发布JUnit测试结果报告”操作。
我决定发布新答案,因为一些现有答案已过时或不完整。
首先:没有类似的东西JUnit XML Format Specification,仅仅是因为JUnit不产生任何类型的XML或HTML报告。
XML报告生成本身来自Ant JUnit任务/ Maven Surefire插件/ Gradle(用于运行测试的任何一种)。XML报告格式最初由Ant引入,后来由Maven(和Gradle)改编。
如果有人只需要一种正式的XML格式,则:
希望它能帮助到别人。
**/build/test-results/**/TEST-*.xml