Code coverage#2165
Open
spetersenms wants to merge 99 commits intomicrosoft:mainfrom
Open
Conversation
mazhelez
reviewed
Apr 9, 2026
Guard optional hashtable property accesses that throw PropertyNotFoundException under Set-StrictMode -Version 2.0: - Add Test-PropertyExists helper for safe property checks on both hashtables and PSCustomObjects - Guard .SourceInfo access on coverage data hashtables with ContainsKey checks in CoberturaFormatter and CoverageProcessor - Guard .ExecutableLines, .RelativePath, .Procedures, and .ExecutableLineNumbers sub-property access on SourceInfo - Guard .Type access in Get-ProcedureCoverage with fallback - Guard property access in Read-AppJson for missing keys - Fix .Count on null in BCCoverageParser empty file path - Wrap Measure-Object .Sum calls with empty collection check Co-authored-by: Copilot <[email protected]>
The MergeCoverage job runs unconditionally but its steps are already gated by hashFiles checks on cobertura.xml. Adding a comment explaining why job-level gating (via Initialization outputs) is not worth the added complexity for ~20s of savings. Co-authored-by: Copilot <[email protected]>
Use ContainsKey/GetEnumerator for hashtable access. Always write to _merged/ directory. Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds opt-in code coverage collection to AL-Go for GitHub by introducing an AL-based test runner capable of exporting BC coverage data, converting it to Cobertura XML, publishing per-project artifacts, and generating merged/visual summaries in workflows.
Changes:
- Introduces a new
TestRunnermodule to run tests with optional code coverage collection and to convert BC coverage output into Cobertura XML. - Adds new actions (
BuildCodeCoverageSummary,MergeCoverageSummaries) plus workflow/template updates to publish and merge coverage artifacts and render job summaries. - Adds new settings (
enableCodeCoverage,codeCoverageSetup) with schema + documentation updates and supporting Pester tests + test data.
Reviewed changes
Copilot reviewed 61 out of 66 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/CI.yaml | Runs new CodeCoverage Pester test suite in CI matrix. |
| .pre-commit-config.yaml | Excludes intentionally malformed Cobertura XML test fixture from XML lint hook. |
| Actions/.Modules/ReadSettings.psm1 | Adds default values for enableCodeCoverage + codeCoverageSetup. |
| Actions/.Modules/settings.schema.json | Adds schema definitions for new coverage settings. |
| Actions/.Modules/TestRunner/ALTestRunner.psm1 | Public entrypoint to run tests and emit results/coverage. |
| Actions/.Modules/TestRunner/TestResultFormatter.psm1 | Converts test runner results into JUnit/XUnit formats. |
| Actions/.Modules/TestRunner/CoverageProcessor/BCCoverageParser.psm1 | Parses BC coverage exports (CSV/XML) into objects. |
| Actions/.Modules/TestRunner/CoverageProcessor/CoberturaFormatter.psm1 | Formats processed coverage into Cobertura XML. |
| Actions/.Modules/TestRunner/CoverageProcessor/ALSourceParser.psm1 | Parses AL source to map executable lines/procedures for accurate coverage. |
| Actions/.Modules/TestRunner/CoverageProcessor/CoverageProcessor.psm1 | Orchestrates conversion/merge pipeline for BC coverage → Cobertura + stats. |
| Actions/.Modules/TestRunner/Internal/ALTestRunnerInternal.psm1 | Internal test execution loop + optional coverage collection hooks. |
| Actions/.Modules/TestRunner/Internal/ClientContext.ps1 | Implements BC client session plumbing (incl. PS7 SSL handler support). |
| Actions/.Modules/TestRunner/Internal/ClientSessionManager.psm1 | Manages client sessions + SSL verification toggling behavior. |
| Actions/.Modules/TestRunner/Internal/Constants.ps1 | Defines shared constants (test runner IDs, coverage exporter IDs, etc.). |
| Actions/.Modules/TestRunner/Internal/CoverageCollector.psm1 | Collects coverage output/map from the test tool page. |
| Actions/.Modules/TestRunner/Internal/ModuleInit.ps1 | Loads client DLLs and (on PS7) downloads required WCF dependencies. |
| Actions/.Modules/TestRunner/Internal/TestFormHelpers.psm1 | Encapsulates test tool page interactions (filters, isolation, coverage controls). |
| Actions/.Modules/TestRunner/Internal/AadTokenProvider.ps1 | Adds an AAD token provider helper (currently with install-time side effects). |
| Actions/.Modules/TestRunner/Internal/BCPTTestRunnerInternal.psm1 | Adds internal BCPT test runner support (includes AAD helper wiring). |
| Actions/BuildCodeCoverageSummary/action.yaml | New composite action to render coverage summary from Cobertura artifact. |
| Actions/BuildCodeCoverageSummary/BuildCodeCoverageSummary.ps1 | Generates GitHub step summary from {project}/.buildartifacts/CodeCoverage/cobertura.xml. |
| Actions/BuildCodeCoverageSummary/README.md | Documents usage/inputs for coverage summary action. |
| Actions/MergeCoverageSummaries/action.yaml | New composite action to merge multiple Cobertura artifacts. |
| Actions/MergeCoverageSummaries/MergeCoverageSummaries.ps1 | Finds cobertura inputs, merges XML + stats, writes consolidated summary. |
| Actions/MergeCoverageSummaries/CoberturaMerger.psm1 | Implements Cobertura XML line-level merging + stats merging. |
| Actions/MergeCoverageSummaries/README.md | Documents merge action usage, behavior, and expected artifact layout. |
| Actions/CalculateArtifactNames/action.yaml | Adds CodeCoverage artifact name output wiring. |
| Actions/CalculateArtifactNames/CalculateArtifactNames.ps1 | Produces CodeCoverageArtifactsName alongside existing artifact name outputs. |
| Actions/CheckForUpdates/CheckForUpdates.HelperFunctions.ps1 | Ensures PostProcess.needs includes MergeCoverage when present in workflow YAML. |
| Actions/RunPipeline/action.yaml | Adds projectDependenciesJson input and passes through to RunPipeline.ps1. |
| Actions/RunPipeline/RunPipeline.ps1 | Imports test runner, injects coverage-enabled RunTestsInBcContainer override, and converts .dat coverage to Cobertura after tests. |
| RELEASENOTES.md | Notes new (Preview) code coverage feature and points to documentation. |
| Scenarios/settings.md | Documents enableCodeCoverage + codeCoverageSetup and clarifies override interaction. |
| Scenarios/CodeCoverage.md | New scenario doc explaining enabling, config, outputs, limitations, and custom override usage. |
| Templates/AppSource App/.github/workflows/_BuildALGoProject.yaml | Uploads CodeCoverage artifacts and runs BuildCodeCoverageSummary when Cobertura exists. |
| Templates/AppSource App/.github/workflows/PullRequestHandler.yaml | Adds MergeCoverage job and wires StatusCheck needs. |
| Templates/AppSource App/.github/workflows/CICD.yaml | Adds MergeCoverage job and includes it in PostProcess needs. |
| Templates/Per Tenant Extension/.github/workflows/_BuildALGoProject.yaml | Uploads CodeCoverage artifacts and runs BuildCodeCoverageSummary when Cobertura exists. |
| Templates/Per Tenant Extension/.github/workflows/PullRequestHandler.yaml | Adds MergeCoverage job and wires StatusCheck needs. |
| Templates/Per Tenant Extension/.github/workflows/CICD.yaml | Adds MergeCoverage job and includes it in PostProcess needs. |
| Tests/CodeCoverage/ALSourceParser.Test.ps1 | Pester tests for AL source parsing used by coverage formatting. |
| Tests/CodeCoverage/BCCoverageParser.Test.ps1 | Pester tests for parsing BC coverage CSV/XML formats. |
| Tests/CodeCoverage/BuildCodeCoverageSummary.Test.ps1 | Pester tests for summary generation sizing/output behaviors. |
| Tests/CodeCoverage/CoberturaFormatter.Test.ps1 | Pester tests for Cobertura XML generation and stats correctness. |
| Tests/CodeCoverage/CoberturaMerger.Test.ps1 | Pester tests for Cobertura merge behavior and stats recalculation. |
| Tests/CodeCoverage/CoverageProcessor.Test.ps1 | Pester tests for end-to-end conversion/merge to Cobertura + stats JSON. |
| Tests/CodeCoverage/CoverageReportGenerator.Test.ps1 | Pester tests for markdown report generation from Cobertura. |
| Tests/CodeCoverage/MergeCoverageSummaries.Test.ps1 | Pester tests for artifact discovery, merging, and summary constraints. |
| Tests/CodeCoverage/TestData/ALFiles/complex-codeunit.al | Fixture for AL parsing and executable line detection. |
| Tests/CodeCoverage/TestData/ALFiles/sample-codeunit.al | Fixture for AL parsing and procedure mapping. |
| Tests/CodeCoverage/TestData/ALFiles/sample-page.al | Fixture for AL object parsing beyond codeunits. |
| Tests/CodeCoverage/TestData/CoberturaFiles/cobertura-empty.xml | Fixture for empty Cobertura handling. |
| Tests/CodeCoverage/TestData/CoberturaFiles/cobertura-malformed.xml | Fixture for malformed Cobertura handling. |
| Tests/CodeCoverage/TestData/CoberturaFiles/cobertura1.xml | Fixture for Cobertura merge/summary tests. |
| Tests/CodeCoverage/TestData/CoberturaFiles/cobertura2.xml | Fixture for Cobertura merge/summary tests. |
| Tests/CodeCoverage/TestData/CoverageFiles/empty-coverage.dat | Fixture for empty BC coverage input handling. |
| Tests/CodeCoverage/TestData/CoverageFiles/malformed-coverage.dat | Fixture for malformed BC coverage CSV input handling. |
| Tests/CodeCoverage/TestData/CoverageFiles/sample-coverage.dat | Fixture for BC CSV coverage parsing and stats. |
| Tests/CodeCoverage/TestData/CoverageFiles/sample-coverage.xml | Fixture for BC XML coverage parsing and stats. |
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Code Coverage Support for AL-Go
This adds Code coverage support to AL-Go for GitHub.
Overview
I use a modified version of the internal test runner, somewhat similar to the one in container helper, which support code coverage. On top of that, I have made a custom parser from the raw csv format we get from BC to the industry standard Cobertura XML format. There is also new action to create a visual overview in builds. The raw data, including the Cobertura xml is included in artifacts so the user can further analyze in 3rd party tools.
As AL-Go currently relies on container helper to run tests, this feature currently uses the test override to use the modified test runner. In the future when we move away from container helper, this test runner should completely replace the old one.
As this is a pretty large feature, it is not turned on by default. I also could not test all possible cases, so there might be some situations where tests do not work on the new runner, in which case the old one should be used.
Key Components
Test Runner Module
The
.Modules/TestRunnermodule has been added as a complete package for handling test running and code coverage generation.Core Modules:
BCCoverageParser.psm1- Parses Business Central coverage files (CSV and XML formats from XMLport 130470/130471/130007)ALSourceParser.psm1- Analyzes AL source code to identify objects, procedures, and executable linesCoverageProcessor.psm1- Orchestrates the coverage processing pipelineCoberturaFormatter.psm1- Converts BC coverage data to Cobertura XML formatCoberturaMerger.psm1- Merges multiple Cobertura reportsCoverageReportGenerator.psm1- Generates markdown summariesALTestRunner.psm1- Executes AL test suites with optional coverage collectionActions
RunPipeline- Enhanced to support coverage collection during test executionBuildCodeCoverageSummary- Generates coverage reports and artifactsMergeCoverageSummaries- Combines coverage from multiple projects or test runsSettings
Two new settings control the feature:
{ "enableCodeCoverage": false, "codeCoverageSetup": { "trackingType": "PerRun", "produceCodeCoverageMap": "PerCodeunit", "excludeFilesPattern": ["*.Test.al", *PermissionSet*] } }The feature is opt-in and disabled by default to avoid impact on existing workflows.
Technical Details
Breaking Changes
None. The feature is opt-in. Do note however, that the feature is not currently not supported if test override is already used.
Related to issue: #
✅ Checklist