From a4f65400b52334afd49c52ab4861b1cf62a42807 Mon Sep 17 00:00:00 2001 From: Jeffrey Bulanadi Date: Thu, 30 Apr 2026 11:55:58 +0800 Subject: [PATCH 1/2] Surface empty BCPT results as a warning instead of silent success When BCPT tests ran but produced no log entries (e.g. because the test runner exited early or the suite codeunit IDs did not match), the results file contained no entries. GetBcptSummaryMD returned an empty string, the AnalyzeTests step wrote nothing to the job summary, and the build succeeded with no indication that performance tests did not produce output. Changes: - TestResultAnalyzer.ps1: Differentiate between results file not existing (return empty string) and results file existing but containing no entries (return an informational message so the GitHub summary shows a visible indication that no measurements were recorded). - AnalyzeTests.ps1: Emit a GitHub Actions warning annotation when the BCPT results file is present but GetBcptSummaryMD returns empty, as a defence-in-depth measure. - AnalyzeTests.Test.ps1: Add tests for ReadBcptFile and GetBcptSummaryMD when the file does not exist and when it exists but contains no entries. Fixes https://github.com/microsoft/AL-Go/issues/2158 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Actions/AnalyzeTests/AnalyzeTests.ps1 | 3 +++ Actions/AnalyzeTests/TestResultAnalyzer.ps1 | 6 ++++- Tests/AnalyzeTests.Test.ps1 | 29 +++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Actions/AnalyzeTests/AnalyzeTests.ps1 b/Actions/AnalyzeTests/AnalyzeTests.ps1 index cf3b223828..dd647752bb 100644 --- a/Actions/AnalyzeTests/AnalyzeTests.ps1 +++ b/Actions/AnalyzeTests/AnalyzeTests.ps1 @@ -29,6 +29,9 @@ switch ($testType) { -baseLinePath $bcptBaseLineFile ` -thresholdsPath $bcptThresholdsFile ` -bcptThresholds ($settings.bcptThresholds | ConvertTo-HashTable) + if (-not $testResultsSummaryMD -and (Test-Path -Path $bcptTestResultsFile -PathType Leaf)) { + OutputWarning "BCPT tests were run but produced no results. The BCPT test suite may have failed to start or the test codeunits exited without recording any measurements." + } $testTitle = "Performance test results" } 'pageScripting' { diff --git a/Actions/AnalyzeTests/TestResultAnalyzer.ps1 b/Actions/AnalyzeTests/TestResultAnalyzer.ps1 index 1beae6e4fa..78b3d38401 100644 --- a/Actions/AnalyzeTests/TestResultAnalyzer.ps1 +++ b/Actions/AnalyzeTests/TestResultAnalyzer.ps1 @@ -295,9 +295,13 @@ function GetBcptSummaryMD { ) $bcpt = ReadBcptFile -bcptTestResultsFile $bcptTestResultsFile - if (-not $bcpt) { + if ($null -eq $bcpt) { return '' } + if ($bcpt.Count -eq 0) { + # File exists but contained no log entries - test run produced no output + return "No BCPT results were recorded. The BCPT test suite may have failed to start or the test codeunits exited without recording any measurements.`n`n> Verify that the BCPT suite definition matches the published test codeunit IDs and that the test codeunits are reachable from the test runner." + } $baseLine = ReadBcptFile -bcptTestResultsFile $baseLinePath if ($baseLine) { if ($null -eq $bcptThresholds) { diff --git a/Tests/AnalyzeTests.Test.ps1 b/Tests/AnalyzeTests.Test.ps1 index b911958e9a..b40eeff0ef 100644 --- a/Tests/AnalyzeTests.Test.ps1 +++ b/Tests/AnalyzeTests.Test.ps1 @@ -78,6 +78,35 @@ Describe "AnalyzeTests Action Tests" { $bcpt."SUITE1"."1".operations."operation2".measurements.Count | should -Be 4 } + It 'Test ReadBcptFile returns null when file does not exist' { + . (Join-Path $scriptRoot '../AL-Go-Helper.ps1') + . (Join-Path $scriptRoot 'TestResultAnalyzer.ps1') + $bcpt = ReadBcptFile -bcptTestResultsFile 'non-existent-file.json' + $bcpt | Should -BeNullOrEmpty + } + + It 'Test GetBcptSummaryMD returns empty string when file does not exist' { + . (Join-Path $scriptRoot '../AL-Go-Helper.ps1') + . (Join-Path $scriptRoot 'TestResultAnalyzer.ps1') + $md = GetBcptSummaryMD -bcptTestResultsFile 'non-existent-file.json' + $md | Should -Be '' + } + + It 'Test GetBcptSummaryMD returns warning message when file exists but contains no entries' { + . (Join-Path $scriptRoot '../AL-Go-Helper.ps1') + . (Join-Path $scriptRoot 'TestResultAnalyzer.ps1') + $emptyResultsFile = Join-Path ([System.IO.Path]::GetTempPath()) "$([GUID]::NewGuid().ToString()).json" + try { + $null | ConvertTo-Json -Depth 99 | Set-Content -Path $emptyResultsFile -Encoding UTF8 + $md = GetBcptSummaryMD -bcptTestResultsFile $emptyResultsFile + $md | Should -Not -BeNullOrEmpty + $md | Should -Match 'No BCPT results were recorded' + } + finally { + Remove-Item -Path $emptyResultsFile -Force -ErrorAction SilentlyContinue + } + } + It 'Test GetBcptSummaryMD (no baseline)' { . (Join-Path $scriptRoot '../AL-Go-Helper.ps1') . (Join-Path $scriptRoot 'TestResultAnalyzer.ps1') From 794f949418d5d686cc84f819d72810780d7c37ce Mon Sep 17 00:00:00 2001 From: Jeffrey Bulanadi Date: Thu, 30 Apr 2026 12:38:57 +0800 Subject: [PATCH 2/2] Address bot review: move warning to GetBcptSummaryMD and use empty array in test - TestResultAnalyzer.ps1: Emit OutputWarning directly inside GetBcptSummaryMD when the results file exists but contains no entries, so the annotation is always surfaced at the right call site. - AnalyzeTests.ps1: Remove the now-unreachable defensive warning block identified by the bot; the warning is handled in GetBcptSummaryMD. - AnalyzeTests.Test.ps1: Use Should -Be null (not -BeNullOrEmpty) to assert the exact return value of ReadBcptFile for a missing file. Use an empty JSON array '[]' instead of 'null' to better represent a real empty BCPT results file. Add Mock for OutputWarning to assert the warning is emitted when no entries are found. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Actions/AnalyzeTests/AnalyzeTests.ps1 | 3 --- Actions/AnalyzeTests/TestResultAnalyzer.ps1 | 1 + Tests/AnalyzeTests.Test.ps1 | 7 +++++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Actions/AnalyzeTests/AnalyzeTests.ps1 b/Actions/AnalyzeTests/AnalyzeTests.ps1 index dd647752bb..cf3b223828 100644 --- a/Actions/AnalyzeTests/AnalyzeTests.ps1 +++ b/Actions/AnalyzeTests/AnalyzeTests.ps1 @@ -29,9 +29,6 @@ switch ($testType) { -baseLinePath $bcptBaseLineFile ` -thresholdsPath $bcptThresholdsFile ` -bcptThresholds ($settings.bcptThresholds | ConvertTo-HashTable) - if (-not $testResultsSummaryMD -and (Test-Path -Path $bcptTestResultsFile -PathType Leaf)) { - OutputWarning "BCPT tests were run but produced no results. The BCPT test suite may have failed to start or the test codeunits exited without recording any measurements." - } $testTitle = "Performance test results" } 'pageScripting' { diff --git a/Actions/AnalyzeTests/TestResultAnalyzer.ps1 b/Actions/AnalyzeTests/TestResultAnalyzer.ps1 index 78b3d38401..7237072f97 100644 --- a/Actions/AnalyzeTests/TestResultAnalyzer.ps1 +++ b/Actions/AnalyzeTests/TestResultAnalyzer.ps1 @@ -300,6 +300,7 @@ function GetBcptSummaryMD { } if ($bcpt.Count -eq 0) { # File exists but contained no log entries - test run produced no output + OutputWarning "BCPT tests were run but produced no results. The BCPT test suite may have failed to start or the test codeunits exited without recording any measurements." return "No BCPT results were recorded. The BCPT test suite may have failed to start or the test codeunits exited without recording any measurements.`n`n> Verify that the BCPT suite definition matches the published test codeunit IDs and that the test codeunits are reachable from the test runner." } $baseLine = ReadBcptFile -bcptTestResultsFile $baseLinePath diff --git a/Tests/AnalyzeTests.Test.ps1 b/Tests/AnalyzeTests.Test.ps1 index b40eeff0ef..f53005c5f6 100644 --- a/Tests/AnalyzeTests.Test.ps1 +++ b/Tests/AnalyzeTests.Test.ps1 @@ -82,7 +82,7 @@ Describe "AnalyzeTests Action Tests" { . (Join-Path $scriptRoot '../AL-Go-Helper.ps1') . (Join-Path $scriptRoot 'TestResultAnalyzer.ps1') $bcpt = ReadBcptFile -bcptTestResultsFile 'non-existent-file.json' - $bcpt | Should -BeNullOrEmpty + $bcpt | Should -Be $null } It 'Test GetBcptSummaryMD returns empty string when file does not exist' { @@ -96,11 +96,14 @@ Describe "AnalyzeTests Action Tests" { . (Join-Path $scriptRoot '../AL-Go-Helper.ps1') . (Join-Path $scriptRoot 'TestResultAnalyzer.ps1') $emptyResultsFile = Join-Path ([System.IO.Path]::GetTempPath()) "$([GUID]::NewGuid().ToString()).json" + $script:warningCount = 0 + Mock OutputWarning { Param([string] $message) Write-Host "WARNING: $message"; $script:warningCount++ } try { - $null | ConvertTo-Json -Depth 99 | Set-Content -Path $emptyResultsFile -Encoding UTF8 + Set-Content -Path $emptyResultsFile -Value '[]' -Encoding UTF8 $md = GetBcptSummaryMD -bcptTestResultsFile $emptyResultsFile $md | Should -Not -BeNullOrEmpty $md | Should -Match 'No BCPT results were recorded' + $script:warningCount | Should -Be 1 } finally { Remove-Item -Path $emptyResultsFile -Force -ErrorAction SilentlyContinue