Skip to content

Add Test Isolation support#2216

Open
Drakonian wants to merge 7 commits into
microsoft:mainfrom
Drakonian:AddTestIsolationSupport2
Open

Add Test Isolation support#2216
Drakonian wants to merge 7 commits into
microsoft:mainfrom
Drakonian:AddTestIsolationSupport2

Conversation

@Drakonian

Copy link
Copy Markdown

Add Test Isolation support

Why

BC runtime 16 (2025 W2) added the RequiredTestIsolation property on test codeunits. The standard BC test runner has a single, fixed TestIsolation value, so any project that mixes codeunits with different isolation requirements cannot run them all under one runner, those tests get excluded from CI.

AL-Go today makes one blanket Run-TestsInBcContainer call per test app under the default runner. Test codeunits that need a non-default runner (e.g. TestIsolation = Disabled for long-running integration tests that must not roll back) have to be placed in disabledtests.json and run manually, losing CI coverage.

This contribution closes that gap.

Discussion reference

#1565

How

A new opt-in testIsolation setting lets projects partition the test stage:

"testIsolation": {
  "enabled": true,
  "defaultRunnerCodeunitId": 0,
  "partitions": [
    { "runnerCodeunitId": 130451, "codeunits": "99209" }
  ]
}

When enabled, RunPipeline installs a -RunTestsInBcContainer scriptblock into Run-AlPipeline that, per test app:

  1. Invokes Run-TestsInBcContainer once per entry in partitions, with -testRunnerCodeunitId and -testCodeunitRange set from the entry.
  2. Issues one trailing call under defaultRunnerCodeunitId whose -testCodeunitRange is the negation of every explicit partition's filter, so codeunits not in any partition run exactly once under the default runner.

The scriptblock forwards all other Run-AlPipeline parameters verbatim, so disabledTests.json handling, JUnit result appending, container lifecycle, and useCompilerFolder support continue to work unchanged. Feature is strictly additive and off by default.

Validation

  • Pester suite passes locally and in CI.
  • End-to-end on a real BC 27 project (parallel-worker-bc, green): 33 integration tests that had been permanently disabled via disabledtests.json for lack of a TestIsolation = Disabled runner now execute successfully under standard BCApps runner 130451, while the remaining test codeunits (99201–99203) run under the default runner in the same build — proving both the partition call and the negated-filter fallback work against real BcContainerHelper.

@Drakonian Drakonian requested a review from a team as a code owner April 19, 2026 21:20
Copilot AI review requested due to automatic review settings April 19, 2026 21:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds opt-in “test isolation” support to AL-Go so a single test stage can be partitioned across multiple test runners (to satisfy mixed RequiredTestIsolation requirements) while preserving existing Run-AlPipeline behaviors like disabled tests handling and result aggregation.

Changes:

  • Introduces new testIsolation setting (defaults, schema validation, and documentation).
  • Adds a RunTestsInBcContainer override hook in RunPipeline that runs partitions + a default “everything else” pass.
  • Adds Pester coverage for the new partitioning scriptblock and settings schema shape/validation.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
Tests/TestIsolation.Test.ps1 New Pester tests covering partition invocation behavior, negated default filter construction, parameter forwarding, and failure aggregation.
Tests/ReadSettings.Test.ps1 Extends schema tests to cover testIsolation defaults and schema validation rules.
Scenarios/settings.md Documents the new testIsolation setting in the settings reference table.
Scenarios/TestIsolation.md Adds a dedicated scenario doc describing configuration, semantics, compatibility, and edge cases.
RELEASENOTES.md Adds release notes entry describing the new opt-in test isolation partitioning capability.
README.md Links the new Test Isolation scenario from the main scenarios list.
Actions/RunPipeline/RunPipeline.ps1 Wires testIsolation into Run-AlPipeline by injecting a partitioning RunTestsInBcContainer scriptblock and emitting telemetry.
Actions/.Modules/settings.schema.json Adds testIsolation schema (object shape, required keys, and partition entry validation).
Actions/.Modules/TestIsolation.psm1 New module that builds the partitioning scriptblock and computes the negated default codeunit-range filter.
Actions/.Modules/ReadSettings.psm1 Adds testIsolation to default settings so it participates in the normal settings merge+validation pipeline.

Comment thread Actions/.Modules/TestIsolation.psm1 Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Comment thread Actions/RunPipeline/RunPipeline.ps1 Outdated
Drakonian added 2 commits July 4, 2026 19:50
(e.g. '..60199|60302..') instead of '<>' negation, which the BC
filter grammar does not support for ranges; skip the call when
partitions cover the entire ID space and warn on overlaps

Wrap an existing RunTestsInBcContainer override instead of
replacing it (new InnerScriptBlock parameter)

Restrict codeunits filter syntax in the schema to single IDs and
closed ranges joined by '|'

Fix schema negative tests passing vacuously when no error was
thrown; add coverage for complement, wrapping and validation
@Drakonian

Copy link
Copy Markdown
Author

@mazhelez Thanks for the review, both points are addressed in the latest commit, plus one issue I found while re-checking the filter logic:

1. Existing RunTestsInBcContainer override is now wrapped, not replaced. New-PartitionedTestRunnerScriptBlock accepts an InnerScriptBlock; when a project ships .AL-Go/RunTestsInBcContainer.ps1, each partitioned call is routed through that override with testCodeunitRange/testRunnerCodeunitId added to the parameter hashtable. Documented in the scenario doc (the override must splat $parameters through for the filter to take effect).

2. Regarding an alternative without the override hook: Run-TestsInBcContainer has -requiredTestIsolation, but Run-AlPipeline doesn't expose it (and it requires runtime 16+ plus tests that actually declare RequiredTestIsolation). Manual partitions work on any runtime and runner. A future partitionBy: "requiredTestIsolation" mode could be layered on top of this setting without breaking its shape.

3. Fixed the default-runner exclusion filter for range partitions. The BC filter grammar only supports <> against single values, so <>60200..60299 would have been an invalid filter at runtime. AL-Go now computes the complement of all partitions instead (e.g. ..60199|60302..), which is plain documented filter syntax. Along with this:

  • codeunits is schema-restricted to single IDs and closed ranges joined by | (the subset a complement can be computed for)
  • overlapping partitions emit a pipeline warning
  • the trailing default-runner call is skipped when partitions cover the entire ID space

Comment thread RELEASENOTES.md
Comment thread RELEASENOTES.md
@Drakonian

Copy link
Copy Markdown
Author

@spetersenms should be good now

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.

4 participants