我有一些通过Cruisecontrol.net运行的 C++ 项目。作为构建过程的一部分,我们编译和运行Boost.Test单元测试套件。我将这些配置为转储 XML 日志文件。虽然格式类似于 JUnit/NUnit,但并不完全相同(并且缺少一些信息),因此 Cruisecontrol.net 无法获取它们。我想知道是否有人创建(或知道)现有的 XSL 转换,它将 Boost.Test 结果转换为 JUnit/NUnit 格式,或者直接转换为可呈现的(html)格式。
谢谢!
我有一些通过Cruisecontrol.net运行的 C++ 项目。作为构建过程的一部分,我们编译和运行Boost.Test单元测试套件。我将这些配置为转储 XML 日志文件。虽然格式类似于 JUnit/NUnit,但并不完全相同(并且缺少一些信息),因此 Cruisecontrol.net 无法获取它们。我想知道是否有人创建(或知道)现有的 XSL 转换,它将 Boost.Test 结果转换为 JUnit/NUnit 格式,或者直接转换为可呈现的(html)格式。
谢谢!
我正在开发自己的 Boost.Test -> JUnit XSL。请注意,这旨在使用Boost.Test的 XML报告输出 - 而不是日志输出。这是一项正在进行的工作 - 这是我到目前为止所拥有的:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl">
<xsl:output method="xml"
indent="yes"/>
<xsl:template match="TestResult">
<test-results>
<xsl:attribute name="total">
<xsl:value-of select="sum(./TestSuite/@test_cases_passed) + sum(./TestSuite/@test_cases_failed) + sum(./TestSuite/@test_cases_skipped) + sum(./TestSuite/@test_cases_aborted)"/>
</xsl:attribute>
<xsl:attribute name="failures">
<xsl:value-of select="sum(./TestSuite/@test_cases_failed) + sum(./TestSuite/@test_cases_aborted)"/>
</xsl:attribute>
<xsl:attribute name="skipped">
<xsl:value-of select="sum(./TestSuite/@test_cases_skipped)"/>
</xsl:attribute>
<xsl:attribute name="not-run">
<xsl:value-of select="sum(./TestSuite/@test_cases_skipped)"/>
</xsl:attribute>
<xsl:call-template name="testSuite" />
</test-results>
</xsl:template>
<xsl:template name="testSuite">
<xsl:for-each select="TestSuite">
<test-suite>
<xsl:call-template name="testAttributes" />
<results>
<xsl:call-template name="testSuite" />
<xsl:for-each select="TestCase">
<test-case>
<xsl:call-template name="testAttributes" />
</test-case>
</xsl:for-each>
</results>
</test-suite>
</xsl:for-each>
</xsl:template>
<xsl:template name="testAttributes">
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:attribute name="success">
<xsl:choose>
<xsl:when test="@result = 'passed'">True</xsl:when>
<xsl:when test="@result != 'passed'">False</xsl:when>
</xsl:choose>
</xsl:attribute>
<xsl:attribute name="executed">True</xsl:attribute>
<xsl:attribute name="time">0</xsl:attribute>
<xsl:attribute name="asserts">
<xsl:value-of select="@assertions_failed + @assertions_passed"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
我已将此集成到我的构建过程中,并且它被 ccnet 很好地拾取和处理。它并不完美,但它比我之前完全没有报告的情况要好。我愿意接受有关如何将 Boost.Test 数据映射到 JUnit 报告的“total”、“failures”、“skipped”和“not-run”字段的建议。此外,不幸的是,错误详细数据(指示故障的性质和发生故障的文件/行号)仅打印到日志中,而不是报告中,所以我必须“合并”两者才能得到所有我希望拥有的数据。
感谢上面 Stuart Lange 的回答,我能够获得 Boost.Test 的输出以与我们的 Bamboo 构建系统集成。Bamboo 在此处描述了他们可以摄取的格式:
http://confluence.atlassian.com/display/BAMBOO/JUnit+parsing+in+Bamboo
所以我使用上面的 Stuart Lange 的 XSL 作为起点,最后得到了这个:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl">
<xsl:output method="xml"
indent="yes"/>
<xsl:template match="TestResult">
<xsl:call-template name="testSuite" />
</xsl:template>
<xsl:template name="testSuite">
<xsl:for-each select="TestSuite">
<testsuite>
<xsl:attribute name="errors">
<xsl:value-of select="@test_cases_failed + @test_cases_aborted"/>
</xsl:attribute>
<xsl:attribute name="tests">
<xsl:value-of select="@test_cases_passed + @test_cases_failed + @test_cases_skipped + @test_cases_aborted"/>
</xsl:attribute>
<xsl:attribute name="skipped">
<xsl:value-of select="@test_cases_skipped"/>
</xsl:attribute>
<xsl:attribute name="failures">
<xsl:value-of select="@test_cases_failed"/>
</xsl:attribute>
<xsl:call-template name="testAttributes" />
<!--results-->
<xsl:call-template name="testSuite" />
<xsl:for-each select="TestCase">
<testcase>
<xsl:call-template name="testAttributes" />
<xsl:call-template name="testCaseElements" />
</testcase>
</xsl:for-each>
<!--/results-->
</testsuite>
</xsl:for-each>
</xsl:template>
<xsl:template name="testAttributes">
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:attribute name="success">
<xsl:choose>
<xsl:when test="@result = 'passed'">True</xsl:when>
<xsl:when test="@result != 'passed'">False</xsl:when>
</xsl:choose>
</xsl:attribute>
<xsl:attribute name="executed">True</xsl:attribute>
<xsl:attribute name="time">0</xsl:attribute>
<xsl:attribute name="asserts">
<xsl:value-of select="@assertions_failed + @assertions_passed"/>
</xsl:attribute>
</xsl:template>
<xsl:template name="testCaseElements">
<xsl:if test="@result != 'passed'">
<failure type="No type reported" message="No message reported"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
当我们调用 Boost.Test 可执行文件时,我们使用以下命令行选项:
--report_format=xml
--report_level=detailed
离开印刷机的 XSL 不是最热门的,但足以看到套件、包含的测试以及 Bamboo 的哪些测试(如果有)失败。
还有一点需要注意的是,使用此方法您只想捕获 stderr 输出。stdout 的内容(至少我们使用 Boost.Test 的方式)会破坏事情。
此 xsl 适用于将 Boost.Test 的 log.xml 转换为 Bamboo 可读的 JUnit xml,并附有消息!: https ://issues.jenkins-ci.org/secure/attachment/19613/boosttest-1.0-to-junit -1.0.xsl
我们使用--report_format=xml --report_level=detailed --log_level=test_suite --log_format=xml
. 你需要 stderr 和 stdout,然后我们将 <TestLog> 替换为 <xml><TestLog> 并将 </TestResult> 替换为 </TestResult><xml>。之后我们虽然很整洁地运行它,最后通过这个 xslt 运行它。
您还必须注意不要在标准输出/错误中包含任何 xml 样式的标签。<foo> 之类的东西可能会破坏转换。
<xsl:for-each select="./TestSuite">
<xsl:variable name="name2" select="@name"/>
<testsuite>
<xsl:attribute name="errors">
<xsl:value-of select="@test_cases_failed" />
</xsl:attribute>
<xsl:attribute name="tests">
<xsl:value-of select="@test_cases_failed + @test_cases_passed + @test_cases_skipped" />
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="@name" />
</xsl:attribute>
<xsl:for-each select="./TestCase">
<xsl:variable name="name3" select="@name"/>
<testcase>
<xsl:attribute name="name">
<xsl:value-of select="@name" />
</xsl:attribute>
<xsl:for-each select="/xml/TestLog/TestSuite[@name=$name1]">
<xsl:for-each select="./TestSuite[@name=$name2]">
<xsl:for-each select="./TestCase[@name=$name3]">
<xsl:for-each select="./TestingTime">
<xsl:attribute name="time">
<xsl:value-of select="./text() div 100000"/>
</xsl:attribute>
</xsl:for-each>
<xsl:for-each select="./Error">
<failure>
<xsl:attribute name="type">AssertionFailedError</xsl:attribute>
<xsl:attribute name="message">
<xsl:value-of select="@file"/>:<xsl:value-of select="@line"/>
</xsl:attribute>
<xsl:copy-of select="./text()"/>
</failure>
</xsl:for-each>
<xsl:for-each select="./Exception">
<failure>
<xsl:attribute name="type">AssertionFailedException</xsl:attribute>
<xsl:attribute name="message">
<xsl:value-of select="@file"/>:<xsl:value-of select="@line"/>
</xsl:attribute>
<xsl:copy-of select="./text()"/>
</failure>
</xsl:for-each>
<system-out>
<xsl:copy-of select="./text()"/>
</system-out>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</testcase>
</xsl:for-each>
</testsuite>
</xsl:for-each>
</testsuite>
有趣的是,以上都没有对我有用,可能是因为更新的 CruiseControl (2.8.4),但无论如何。CruiseControl 会忽略上述转换创建的所有“错误”和“失败”属性,并对子元素进行自己的查询。现在这实际上显示了有多少测试成功,哪些测试失败了。
最好也从 boost 测试日志文件中折叠更具体的失败信息(但也许其他人可以从这里获取)。
关键点:为 Boost.Test 指定以下标志以拆分 stdout/stderr。这是来自 ant 构建脚本的快照:
<exec executable="cmd " dir="bin/x64/Release">
<arg line="/k @{file} --build_info --report_format=xml --report_level=detailed --log_level=all --log_format=xml 1> @{file}.log.xml 2> @{file}.result.xml"/>
</exec>
然后转换它:
<xslt in="@{file}.result.xml" out="@{file}.ccresult.xml" style="transform.xslt" />
实际的 transform.xslt:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/TestResult/TestSuite">
<testsuite>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:for-each select="TestCase">
<testcase>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:if test="@result!='passed'">
<failure>See log file.</failure>
</xsl:if>
</testcase>
</xsl:for-each>
</testsuite>
</xsl:template>
</xsl:stylesheet>