Skip to content

Code coverage#2165

Draft
spetersenms wants to merge 78 commits intomicrosoft:mainfrom
spetersenms:CodeCoverage
Draft

Code coverage#2165
spetersenms wants to merge 78 commits intomicrosoft:mainfrom
spetersenms:CodeCoverage

Conversation

@spetersenms
Copy link
Contributor

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/TestRunner module 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 lines
  • CoverageProcessor.psm1 - Orchestrates the coverage processing pipeline
  • CoberturaFormatter.psm1 - Converts BC coverage data to Cobertura XML format
  • CoberturaMerger.psm1 - Merges multiple Cobertura reports
  • CoverageReportGenerator.psm1 - Generates markdown summaries
  • ALTestRunner.psm1 - Executes AL test suites with optional coverage collection

Actions

  • RunPipeline - Enhanced to support coverage collection during test execution
  • BuildCodeCoverageSummary - Generates coverage reports and artifacts
  • MergeCoverageSummaries - Combines coverage from multiple projects or test runs

Settings

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

  • Add tests (E2E, unit tests)
  • Update RELEASENOTES.md
  • Update documentation (e.g. for new settings or scenarios)
  • Add telemetry

spetersenms and others added 30 commits March 2, 2026 13:39
The module contains test runner infrastructure (client sessions, test form
helpers, result formatting) with code coverage as one capability. TestRunner
better reflects the module's primary responsibility.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
These settings are referenced in RunPipeline.ps1 but were missing from
ReadSettings.psm1 defaults and settings.schema.json. This caused undefined
variable issues when settings were not explicitly provided by users.

Added to ReadSettings.psm1:
- enableCodeCoverage: false (default, opt-in feature)
- codeCoverageSetup: object with trackingType, produceCodeCoverageMap, excludeFilesPattern

Added to settings.schema.json:
- enableCodeCoverage: boolean with description
- codeCoverageSetup: object with enum validation for trackingType and produceCodeCoverageMap

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ALTestRunnerInternal.psm1 line 277 used \ variable but it was not
declared as a function parameter. This caused a strict mode violation error
'variable cannot be retrieved because it has not been set'.

Added [string] \ = \ parameter to match the
pattern used in other functions like Run-Tests (line 205).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ALTestRunnerInternal.psm1 line 136 used undefined variable \ and
line 138 had incomplete string interpolation 'Codeunit \$'.

Fixed by:
- Using \.codeUnit property instead of undefined variable
- Completing string interpolation with \.name
- Adding null check for .codeUnit property for robustness

This was dead code that would crash if reached under strict mode.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Changed all raw warning calls in code coverage code to use OutputWarning from DebugLogHelper module for consistency.

Updated RunPipeline.ps1 (3 instances) and MergeCoverageSummaries.ps1 (1 instance).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Line numbers were sorted as strings (10 < 2) instead of integers.

Added Sort-Object { [int]$_ } to properly sort line numbers numerically in merged Cobertura XML output.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Added null check before accessing projectDeps.PSObject to prevent null reference error when ConvertFrom-Json returns null or empty object.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Added comprehensive documentation covering usage, inputs, outputs, workflow integration example, and explanation of merge behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Wrapped XML parsing in try/catch to gracefully skip malformed files with a warning instead of crashing the entire merge operation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Merge-CoberturaFiles return value was assigned but never used. Function already prints stats internally, so the return value is not needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Variable was misspelled as oututFile in two places. Code worked but reduced readability.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Created test directory structure with test data files for coverage, AL source, and Cobertura XML files. Implemented comprehensive Pester tests for BCCoverageParser module.

Test data includes realistic BC coverage files in CSV format, AL source files, and Cobertura XML samples for merge testing.

Tests cover CSV/XML parsing, auto-detection, grouping, and statistics calculation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
test-parser.ps1 was only used for debugging during test development

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The ModifyBuildWorkflows function used by workflow sanitation tests was not accounting for the new MergeCoverage job when building the PostProcess job's needs array. This caused CICD.yaml comparison to fail.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant