Modules/businessdev.ALbuild.Apps/Private/Get-BcTestResultSummary.ps1

function Get-BcTestResultSummary {
    <#
    .SYNOPSIS
        Summarises an XUnit or JUnit test-result XML document.
    .DESCRIPTION
        Internal, pure helper (no I/O beyond the supplied XML). Counts passed/failed/skipped tests
        and collects failure messages, supporting both XUnit (<test result="Pass|Fail">) and JUnit
        (<testcase> with <failure>/<skipped> children) layouts produced by AL test runners.
    #>

    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory)] [System.Xml.XmlDocument] $Document
    )

    $passed = 0; $failed = 0; $skipped = 0
    $failures = [System.Collections.Generic.List[string]]::new()

    $xunitTests = $Document.SelectNodes("//*[local-name()='test']")
    if ($xunitTests.Count -gt 0) {
        foreach ($test in $xunitTests) {
            $result = ''
            if ($test.Attributes) { foreach ($a in $test.Attributes) { if ($a.Name -ieq 'result') { $result = $a.Value } } }
            switch -Regex ($result) {
                '^(?i)pass'  { $passed++ }
                '^(?i)skip'  { $skipped++ }
                '^(?i)fail'  {
                    $failed++
                    $name = ''
                    if ($test.Attributes) { foreach ($a in $test.Attributes) { if ($a.Name -ieq 'name' -or $a.Name -ieq 'method') { $name = $a.Value } } }
                    $msgNode = $test.SelectSingleNode(".//*[local-name()='message']")
                    $failures.Add("$name`: $(if ($msgNode) { $msgNode.InnerText } else { 'failed' })")
                }
                default { }
            }
        }
    }
    else {
        foreach ($case in $Document.SelectNodes("//*[local-name()='testcase']")) {
            $failureNode = $case.SelectSingleNode("./*[local-name()='failure'] | ./*[local-name()='error']")
            $skippedNode = $case.SelectSingleNode("./*[local-name()='skipped']")
            $name = ''
            if ($case.Attributes) { foreach ($a in $case.Attributes) { if ($a.Name -ieq 'name') { $name = $a.Value } } }
            if ($failureNode) { $failed++; $failures.Add("$name`: $($failureNode.InnerText)") }
            elseif ($skippedNode) { $skipped++ }
            else { $passed++ }
        }
    }

    return [PSCustomObject]@{
        Passed   = $passed
        Failed   = $failed
        Skipped  = $skipped
        Total    = $passed + $failed + $skipped
        Failures = $failures.ToArray()
        Success  = ($failed -eq 0)
    }
}