-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Minor
-
Component/s: xunit-plugin
-
None
-
Environment:xUnit Plugin 3.1.6
Jenkins 2.555.3
BoostTest input (boosttest-1.2-to-junit-4.xsl)
-
3.1.7
What happens
When a Boost.Test <TestSuite> contains BOTH its own direct <TestCase> children AND nested sub-suites that contain test cases, every test case in the sub suites is counted twice in the published results. The reported "passing" total is inflated by the number of such nested cases.
Minimal reproduction see attached files
boost-report.xml:
<TestLog> <TestSuite name="MyModule"> <TestSuite name="GroupA"> <TestCase name="direct_case_in_A"> <TestingTime>1000</TestingTime> </TestCase> <TestSuite name="SubGroup"> <TestCase name="case_in_subgroup"> <TestingTime>1000</TestingTime> </TestCase> </TestSuite> </TestSuite> </TestSuite> </TestLog>
This file contains 2 test cases (direct_case_in_A, case_in_subgroup).
Â
minimalPipeline.groovy:
def getPublisherOptions() {
  [
    $class: 'XUnitPublisher',
    tools: [[
      $class: 'BoostTestJunitHudsonTestType',
      failIfNotNew: false,
      pattern: 'boost-report.xml'
    ]]
  ]
}pipeline {
  agent any
  stages {
    stage('xUnit Plugin 3.1.6 POC') {
      steps {
        step(getPublisherOptions())
      }
    }
  }
}
Expected
2 tests reported
Actual
3 tests reported. The converted JUnit XML emits <testcase name="case_in_subgroup"> twice: once inside GroupA's <testsuite> and once inside SubGroup's <testsuite>.
Note the generated <testsuite tests="..."> header attribute correctly says 2, so the stylesheet's own header count disagrees with the number of <testcase> elements it emits.

Root cause
In boosttest-1.2-to-junit-4.xsl, the named template "testSuite" iterates ALL descendant test cases:
<xsl:for-each select=".//TestCase">
<xsl:call-template name="testCase"/>
</xsl:for-each>
But the caller already visits every suite that has direct test cases (descendant::TestSuite[count(./TestCase) > 0]). So a suite that has both direct cases and sub-suites-with-cases emits the sub-suite cases from the parent AND again from the sub-suite. By contrast, the header "tests" count uses a de-duplicated expression: count(.//TestCase[count(descendant::TestSuite) = 0]), which is why the header and the body disagree.
Suggested fix
In the "testSuite" template, emit only DIRECT test cases:
<xsl:for-each select="./TestCase"> <!-- was: .//TestCase -->
<xsl:call-template name="testCase"/>
</xsl:for-each
Since the caller already visits every suite that has direct <TestCase> children, each case is then emitted exactly once by its own parent suite, and no case is
dropped. Classnames are unchanged.
Verified: with this one-line change the minimal repro reports 2 tests, and a real dataset of 1296 single-test Boost reports drops from 1316 (20 duplicates) back to the correct 1296 passing / 2 skipped.
Â
- links to