Hudson支持的JUnit XML格式规范是什么?

我有Hudson作为持续集成服务器,我想使用选项“发布JUnit测试结果报告”。但是我不使用xUnit工具进行测试,相反,我有运行测试并以简单格式返回结果的shell脚本。我正在考虑制作一个脚本,将这些结果转换为JUnit格式。所以我很有趣的JUnit文件必须看?

258883 次浏览

几个月前我做了类似的事情,结果证明这种简单的格式足以让Hudson接受它作为测试协议:

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

问题安德斯·林达尔上面的回答指的是一个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>

我只是获取了其他人已经链接到的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的工作方式,但在testsuites元素中可以有多个testsuite元素。
  • 每个properties元素可以有多个property子元素。
  • 每个testsuite元素可以有多个testcase子元素。
  • 每个testcase元素可以有多个errorfailuresystem-outsystem-err子元素。

XMLSpear options

我在这方面找不到任何有用的信息,所以我做了一些反复试验。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”和“xUnit”结果有多种模式。

请注意,Jenkins xunit-plugin使用的模式有几个版本(当前的最新版本是junit-10.xsd,它增加了对Erlang/OTP Junit格式的支持)。

一些测试框架以及“xUnit”风格的报告插件也使用它们自己的秘密武器来生成“xUnit”风格的报告,这些报告可能不使用特定的模式(请阅读:它们尝试使用,但工具可能不会针对任何一种模式进行验证)。Jenkins中的Python单元测试?给出了几个这些库的快速比较和生成的xml报告之间的细微差异。

关于使用python的好答案:(有很多方法可以做到) Jenkins中的Python单元测试? < / p > 在我看来,最好的方法是编写python unittest测试安装pytest(类似于'yum install pytest')来获取py。测试安装。 然后像这样运行测试:'py。Test——junitxml results.xml Test .py `。你可以运行任何unittest python脚本并获得jUnit xml结果

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

在jenkins构建配置中,添加一个“发布JUnit测试结果报告”操作,其中包含result.xml和您生成的任何其他测试结果文件。

< p >基本结构 下面是一个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>

我决定发布一个新的答案,因为一些现有的答案已经过时或不完整。

首先:没有类似JUnit XML Format Specification的东西,因为JUnit不生成任何类型的XML或HTML报告。

XML报告生成本身来自Ant JUnit任务/ Maven Surefire Plugin/ Gradle(您用于运行测试的任何一个)。XML报告格式最初由Ant引入,后来由Maven(和Gradle)进行了改编。

如果有人只是需要一个正式的XML格式,那么:

  1. 存在一个maven surefire生成的XML报告的模式,可以在这里找到:surefire-test-report.xsd
  2. 对于蚂蚁生成的XML,有一个第三方模式在这里可用(但它可能有点过时)。

希望它能帮助到一些人。