Convert-ALTestResultToTrxResult.ps1
<#
.SYNOPSIS Get BC test result table and convert it to trx file .DESCRIPTION Get the output of the webservice for reading test results and convert the results to trx file (Visual Studio Test result file) .EXAMPLE PS C:\> Read-ALConfiguration -Path .\ | Test-ALApp -TrxFile <trxfile> -TestCodeunitId <testcodeunitid> -ErrorOnFailedTest Will read project configuration in current folder, run tests and produce the trx file with help of this function .Parameter TrxFile Name of the file to produce .INPUTS Input stream must contain array of BC test results, which must include these members: Codeunit_Name Codeunit_ID Function_Name Execution_Time Start_time Result - value from set Passed|Failed|Inconclusive|Incomplete Error_Message #> function Convert-ALTestResultToTrxResult { param( $TrxFile ) function ParseTimeSpan ($NAVTimeSpan) { $Parts = $NAVTimeSpan.Split('PYMDTHMS') return [Timespan]($Parts[3]+":"+$Parts[5]+":"+ $Parts[6]+":"+$Parts[7]) } $OutFile = Split-Path $TrxFile -Leaf $FileNo = 0 $TestResults = [xml]('<?xml version="1.0" encoding="utf-8" standalone="no"?>'+ '<TestRun>'+ "<TestRunConfiguration name=`"NAV Automati Test Run`">"+ '<Description>This is a default test run configuration for a local test run.</Description>'+ '<TestTypeSpecific /></TestRunConfiguration>'+ '<ResultSummary outcome="Passed">'+ '<Counters total="0" executed="0" passed="0" error="0" failed="0" timeout="0" aborted="0" inconclusive="0" passedButRunAborted="0" notRunnable="0" notExecuted="0" disconnected="0" warning="0" completed="0" inProgress="0" pending="0" />'+ '</ResultSummary>'+ "<Times creation=`"$(Get-Date -Format o)`" queuing=`"$(Get-Date -Format o)`" start=`"`" finish=`"`" />"+ '<TestSettings id="010e155f-ff0f-44f5-a83e-5093c2e8dcc4" name="Settings">'+ '</TestSettings>'+ '<TestDefinitions></TestDefinitions>'+ '<TestLists>'+ '<TestList name="Results Not in a List" id="8c84fa94-04c1-424b-9868-57a2d4851a1d" />'+ '<TestList name="All Loaded Results" id="19431567-8539-422a-85d7-44ee4e166bda" />'+ '</TestLists>'+ '<TestEntries></TestEntries>'+ '<Results></Results>'+ '</TestRun>') $TestRun = $TestResults.SelectSingleNode('/TestRun') $TestRun.SetAttribute('name','NAV Tests') $TestRun.SetAttribute('xmlns','http://microsoft.com/schemas/VisualStudio/TeamTest/2010') $TestRunConfig=$TestResults.SelectSingleNode('/TestRun/TestRunConfiguration') $configid = [guid]::NewGuid() -replace '{}','' $TestRunConfig.SetAttribute('id',$configid) $testrunid = [guid]::NewGuid() -replace '{}','' $TestRun.SetAttribute('id',$testrunid) $TestDefinitions=$TestResults.SelectSingleNode('/TestRun/TestDefinitions') $TestEntries=$TestResults.SelectSingleNode('/TestRun/TestEntries') $Results = $TestResults.SelectSingleNode('/TestRun/Results') $ResultsSummary = $TestResults.SelectSingleNode('/TestRun/ResultSummary') $Times = $TestResults.SelectNodes('/TestRun/Times') foreach ($i in $input) { $TestSuiteName = $i.Codeunit_Name $TestDefinition = $TestResults.CreateElement('UnitTest') $null = $TestDefinitions.AppendChild($TestDefinition) $id = [guid]::NewGuid() -replace '{}','' $FunctionName=$i.Codeunit_ID.ToString()+':'+$i.Function_Name $TestDefinition.SetAttribute('name',$FunctionName) $TestDefinition.SetAttribute('id',$id) $TestDefinition.SetAttribute('storage',"$OutFile") $executionid= [guid]::NewGuid() -replace '{}','' $Execution = $TestResults.CreateElement('Execution') $null = $TestDefinition.AppendChild($Execution) $Execution.SetAttribute('id',$executionid) $TestMethod = $TestResults.CreateElement('TestMethod') $null = $TestDefinition.AppendChild($TestMethod) $TestMethod.SetAttribute('codeBase','COD'+$i.Codeunit_ID.ToString()+'.txt') $TestMethod.SetAttribute('className',$TestSuiteName) $TestMethod.SetAttribute('name',$FunctionName) $TestEntry = $TestResults.CreateElement('TestEntry') $null = $TestEntries.AppendChild($TestEntry) $TestEntry.SetAttribute('testId',$id) $TestEntry.SetAttribute('executionId',$executionid) $TestEntry.SetAttribute('testListId','8c84fa94-04c1-424b-9868-57a2d4851a1d') $Result = $TestResults.CreateElement('UnitTestResult') $null = $Results.AppendChild($Result) $Result.SetAttribute('executionId',$executionid) $Result.SetAttribute('testId',$id) $Result.SetAttribute('testName',$FunctionName) $Result.SetAttribute('computerName',$env:COMPUTERNAME) $Duration = ParseTimeSpan($i.Execution_Time) if ($Duration -lt 0) { $Duration = -$Duration } $RunTime = $Duration #[TimeSpan]::FromMilliseconds( $Result.SetAttribute('duration',$RunTime.ToString()); $StartTime = $i.Start_Time $EndTime = $i.Start_Time + $RunTime $Result.SetAttribute('startTime',$StartTime.ToString('O')) $Result.SetAttribute('endTime',$EndTime.ToString('O')) #Passed,Failed,Inconclusive,Incomplete $ResultsSummary.Counters.executed = (1+$ResultsSummary.Counters.executed).ToString() $ResultsSummary.Counters.total = (1+$ResultsSummary.Counters.total).ToString() if ($Times.GetAttribute('start') -eq '') { $Times.SetAttribute('start',$StartTime.ToString('O')) } $Times.SetAttribute('finish',$EndTime.ToString('O')) switch ($i.Result) { 'Passed' { $TestResult = 'Passed' $ResultsSummary.Counters.completed = (1+$ResultsSummary.Counters.completed).ToString() $ResultsSummary.Counters.passed = (1+$ResultsSummary.Counters.passed).ToString() $ResultsSummary.SetAttribute('outcome','Passed') } 'Failed' { $TestResult = 'Failed' $ResultsSummary.Counters.completed = (1+$ResultsSummary.Counters.completed).ToString() $ResultsSummary.Counters.failed = (1+$ResultsSummary.Counters.failed).ToString() $Output = $TestResults.CreateElement('Output') $null = $Result.AppendChild($Output) $ErrorInfo = $TestResults.CreateElement('ErrorInfo') $null = $Output.AppendChild($ErrorInfo) $Message = $TestResults.CreateElement('Message') $null = $ErrorInfo.AppendChild($Message) $Message.InnerText = $i.Error_Message #if ($line['Call Stack'] -and ($line['Call Stack'].ToString() -gt '')) { # $CallStackData = Get-NAVBlobToString -CompressedByteArray $line['Call Stack'] -ErrorAction SilentlyContinue # if ($CallStackData.Data) { # $StackTrace = $TestResults.CreateElement('StackTrace') # $null = $ErrorInfo.AppendChild($StackTrace) # $StackTrace.InnerText = $CallStackData.Data # } #} $ResultsSummary.SetAttribute('outcome','Failed') } 'Inconclusive' { $TestResult = 'Inconclusive' $ResultsSummary.Counters.completed = (1+$ResultsSummary.Counters.completed).ToString() $ResultsSummary.Counters.inconclusive = (1+$ResultsSummary.Counters.inconclusive).ToString() } 'Incomplete' { #$TestResult = 'Incomplete' $TestResult = 'inProgress' } } $Result.SetAttribute('outcome',$TestResult) $Result.SetAttribute('testListId','8c84fa94-04c1-424b-9868-57a2d4851a1d') $Result.SetAttribute('testType','13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b') } Write-Host "Saving test results to $TrxFile (current working folder is $(Get-Location))" $TestResults.Save($TrxFile) Write-Output $TestResults } |