8

我有一些通过Cruisecontrol.net运行的 C++ 项目。作为构建过程的一部分,我们编译和运行Boost.Test单元测试套件。我将这些配置为转储 XML 日志文件。虽然格式类似于 JUnit/NUnit,但并不完全相同(并且缺少一些信息),因此 Cruisecontrol.net 无法获取它们。我想知道是否有人创建(或知道)现有的 XSL 转换,它将 Boost.Test 结果转换为 JUnit/NUnit 格式,或者直接转换为可呈现的(html)格式。

谢谢!

4

5 回答 5

5

我正在开发自己的 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”字段的建议。此外,不幸的是,错误详细数据(指示故障的性质和发生故障的文件/行号)仅打印到日志中,而不是报告中,所以我必须“合并”两者才能得到所有我希望拥有的数据。

于 2010-06-04T16:17:48.290 回答
5

感谢上面 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 的方式)会破坏事情。

于 2011-01-24T18:49:51.043 回答
2

此 xsl 适用于将 Boost.Test 的 log.xml 转换为 Bamboo 可读的 JUnit xml,并附有消息!: https ://issues.jenkins-ci.org/secure/attachment/19613/boosttest-1.0-to-junit -1.0.xsl

它从这里链接:https ://issues.jenkins-ci.org/browse/JENKINS-7039

于 2011-08-03T14:08:10.727 回答
1

我们使用--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>

于 2010-08-04T15:36:00.993 回答
0

有趣的是,以上都没有对我有用,可能是因为更新的 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&gt; @{file}.log.xml 2&gt; @{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>
于 2012-02-15T18:24:44.043 回答