diff --git a/src/functions/TestResults.NUnit25.ps1 b/src/functions/TestResults.NUnit25.ps1 index a0b8f74ff..9180c4fcd 100644 --- a/src/functions/TestResults.NUnit25.ps1 +++ b/src/functions/TestResults.NUnit25.ps1 @@ -100,11 +100,14 @@ function Write-NUnitTestSuiteElements { $XmlWriter.WriteStartElement('results') + $hasRunnableChildBlocks = $false foreach ($action in $Node.Blocks) { if (-not $action.ShouldRun) { # skip blocks that were discovered but did not run continue } + + $hasRunnableChildBlocks = $true Write-NUnitTestSuiteElements -Node $action -XmlWriter $XmlWriter -Path $action.ExpandedPath } @@ -114,6 +117,9 @@ function Write-NUnitTestSuiteElements { $Node.Tests | & $SafeCommands['Group-Object'] -Property GroupId | & $SafeCommands["Sort-Object"] -Property Name ) + $hasParameterizedTestSuites = 0 -lt @($suites | & $SafeCommands['Where-Object'] { $_.Name }).Count + $requiresTestCaseWrapper = $hasRunnableChildBlocks -or $hasParameterizedTestSuites + foreach ($suite in $suites) { # When group has name it is a parameterized tests (data-generated using -ForEach/TestCases) so we want extra level of nesting for them $testGroupId = $suite.Name @@ -133,8 +139,21 @@ function Write-NUnitTestSuiteElements { continue } + if (-not $testGroupId -and $requiresTestCaseWrapper) { + $testCaseSuiteInfo = Get-TestSuiteInfoForTestResult -TestResult $testCase + + $XmlWriter.WriteStartElement('test-suite') + Write-NUnitTestSuiteAttributes -TestSuiteInfo $testCaseSuiteInfo -XmlWriter $XmlWriter + $XmlWriter.WriteStartElement('results') + } + $suiteName = if ($testGroupId) { $parameterizedSuiteInfo.Name } else { '' } Write-NUnitTestCaseElement -TestResult $testCase -XmlWriter $XmlWriter -Path ($testCase.Path -join '.') -ParameterizedSuiteName $suiteName + + if (-not $testGroupId -and $requiresTestCaseWrapper) { + $XmlWriter.WriteEndElement() + $XmlWriter.WriteEndElement() + } } if ($testGroupId) { @@ -186,6 +205,25 @@ function Get-ParameterizedTestSuiteInfo { return Get-TestSuiteInfo -TestSuite $node -Path $node.Path } +function Get-TestSuiteInfoForTestResult { + param($TestResult) + + $node = [PSCustomObject] @{ + Duration = $TestResult.Duration + FailedCount = 0 + SkippedCount = 0 + InconclusiveCount = 0 + } + + switch ($TestResult.Result) { + Failed { $node.FailedCount = 1; break } + Skipped { $node.SkippedCount = 1; break } + Inconclusive { $node.InconclusiveCount = 1; break } + } + + return Get-TestSuiteInfo -TestSuite $node -Path $TestResult.Path +} + function Get-TestSuiteInfo { param($TestSuite, $Path) # if (-not $Path) { diff --git a/tst/Pester.RSpec.TestResults.NUnit25.ts.ps1 b/tst/Pester.RSpec.TestResults.NUnit25.ts.ps1 index 9f5c6fbc8..1c3e7eacf 100644 --- a/tst/Pester.RSpec.TestResults.NUnit25.ts.ps1 +++ b/tst/Pester.RSpec.TestResults.NUnit25.ts.ps1 @@ -436,6 +436,29 @@ i -PassThru:$PassThru { $null = $xmlResult.Schemas.Add($null, $schemaPath) $xmlResult.Validate( { throw $args[1].Exception }) } + + t 'Should validate against the nunit 2.5 schema when ForEach and plain tests are mixed' { + # https://github.com/pester/Pester/issues/2143 + $sb = { + Describe 'Demonstrate NUnit Problem' { + It 'Should return when type is ' -ForEach @( + @{ Type = 'String'; Variable = [String]'Test'; Result = $true } + @{ Type = 'Int'; Variable = [Int]0; Result = $false } + ) { + ($Variable -is [String]) | Should -Be $Result + } + + It 'A plain non-parameterized test' { 1 | Should -Be 1 } + } + } + $r = Invoke-Pester -Configuration ([PesterConfiguration]@{ Run = @{ ScriptBlock = $sb; PassThru = $true }; Output = @{ Verbosity = 'None' } }) + + $xmlResult = $r | ConvertTo-NUnitReport + + # verify against schema + $null = $xmlResult.Schemas.Add($null, $schemaPath) + $xmlResult.Validate( { throw $args[1].Exception }) + } } b "Exporting multiple containers" {