Resolve test app names from app.json to prevent silent CI test skips#9059
Conversation
BCApps CI dispatched test apps by matching the projects.json key (BuildMetadata.ApplicationName) against the container's installed app name (app.json "name"). When those drift, the app is dropped from the dispatch set and all of its tests are silently skipped while the build stays green. This affected 7 test apps, including Subcontracting Test (~22 test codeunits never run in any CI job). Get-InstalledTestAppNames now resolves each test app's name from its app.json via the new Get-AppNameFromMetadata helper, with a safe fallback to ApplicationName and a CI warning when the two disagree. Adds Pester coverage for the drift, aligned, and fallback cases.
Copilot PR ReviewIteration 3 · Outcome: no-knowledge
Knowledge source: https://github.com/microsoft/BCQuality@822cae1b2771ac25f665f73369f69093bd4fd630 No findings were posted for this iteration. Orchestrator pre-filter (13 file(s) excluded)
Findings produced by the Copilot CLI agent against BCQuality at |
…enLineQuantityReduced Once the CI dispatch fix lets the Subcontracting Test app run, the test WIPTransferRemainderCreatedWhenOpenLineQuantityReduced (codeunit 149911) fails, as already seen in the internal build system. Disable it via the DisabledTests JSON to unblock CI; tracked by AB#641388.
…nGLAccountHasDefaultDeferralTemplateAndJournalTemplNotMandatory The CI dispatch fix lets the Subscription Billing Test app run; it fails in the IT (Italy) build with 'The record in table Payment Lines already exists' while posting the vendor contract purchase invoice (codeunit 139913 Vendor Deferrals Test). Disable it via the DisabledTests JSON to unblock CI; tracked by AB#641478.
…9176) ## What & why The `Run PS Tests` job started failing with: ``` CommandNotFoundException: Could not find Command Get-BcContainerAppInfo ``` `build/scripts/tests/ParallelTestExecution.Test.ps1` (added alongside the test-dispatch fix in #9059) mocks `Get-BcContainerAppInfo`, which is a **BcContainerHelper** cmdlet. That module is loaded when the build runs inside a BC container, but it is **not** present in the `Run PS Tests` runner. Pester 5 cannot mock a command that does not exist, so the mock setup threw and the job failed. This was not caught before merge because locally BcContainerHelper is usually loaded, so the mock resolved against the real cmdlet. ## Linked work <!-- No approved product issue: this is a CI/test-only fix for a break introduced by #9059. --> Fixes # Related to #9059 (introduced the test), supersedes #9174 (which fixed the same failure via a production module wrapper). ## How I validated this - [x] I read the full diff and it contains only changes I intended. - [x] I built the affected app(s) locally with no new analyzer warnings. - [ ] I ran the change in Business Central and confirmed it behaves as expected. - [x] I added or updated tests for the new behavior, or explained below why none are needed. **What I tested and the outcome** - This is a PowerShell test-only change; there is no BC app to build or run. - Reproduced the exact CI condition locally by running Pester with module autoloading disabled so `Get-BcContainerAppInfo` is absent (`Get-Command` returns nothing). Before the fix the mock setup threw `CommandNotFoundException`; after the fix all 5 tests pass. - The stub body intentionally `throw`s to document that it must never execute; the tests passing proves every module call is intercepted by Pester's mock, not the stub. ## Risk & compatibility - Change is confined to a single Pester test file; no production build script or module is touched (this is the key difference from #9174, which added a wrapper to the shipped `ParallelTestExecution.psm1`). - The stub is only defined when the real cmdlet is absent (i.e. the PS test runner) and is removed in `AfterAll`, so it never shadows the real BcContainerHelper cmdlet in a container and does not leak into other test files. - No behavioral change to `ParallelTestExecution.psm1` or the test-dispatch logic. --------- Co-authored-by: aholstrup1 <aholstrup1@users.noreply.github.com>
What & why
BCApps CI was silently skipping entire test apps. The parallel test dispatcher decided which test apps to run by matching each project's
projects.jsonkey (surfaced asBuildMetadata.ApplicationName, and also itsgroups.jsonname) against the app name the container reports (app.json"name"). Those two strings are required to be identical, but when they drift the app is dropped from the dispatch set and all of its tests are silently skipped while the build stays green.This is how
WIPTransferRemainderCreatedWhenOpenLineQuantityReduced(and the rest of the Subcontracting suite) failed in another build system yet never even ran in GitHub CI:Subcontracting-Tests(projects.json key) vsSubcontracting Test(app.json name).A full scan found 7 affected test apps with this drift: Subcontracting Test (~22 test codeunits), Subscription Billing Test (~30), OnPrem Permissions Test, Statistical Accounts Test, Dynamics SL Migration Tests, Tests for MX DIOT Extension, and Basic Experience Tests. All were installed in the container but never dispatched.
Approach
Rather than hand-editing the metadata for all 7 (which fixes the symptom but leaves the mechanism fragile), this makes the dispatcher robust by using the authoritative source of truth.
Get-InstalledTestAppNamesnow resolves each test app's name from itsapp.json(viaAppJsonPath) using a newGet-AppNameFromMetadatahelper, instead of trusting the projects.json key. That is the same string the container reports, so both the installed-name intersection and the downstream name-to-extensionId dispatch map line up, and any future key/name drift self-heals.When the projects.json key and app.json name disagree, it emits a
::warning::naming the offending app so the drift is visible instead of silent, while still dispatching the tests correctly.Verified safe: all 40 legacy-bucket apps and every other test app already have
key == app.json name, so switching the source of truth changes behavior only for the 7 that were broken.Linked work
Fixes #
Related to AB#641388 (Subcontracting
WIPTransferRemainderCreatedWhenOpenLineQuantityReducedfailure surfaced and disabled by this change)Related to AB#641478 (Subscription Billing IT
DeferralsReleaseSucceedsWhenGLAccountHasDefaultDeferralTemplateAndJournalTemplNotMandatoryfailure surfaced and disabled by this change)How I validated this
What I tested and the outcome
build/scripts/tests/ParallelTestExecution.Test.ps1(Pester). 5 tests, all green locally with Pester 5.7.1, covering: name resolved from app.json when it differs from the projects.json key, the aligned case, and both fallbacks (missing app.json path, empty path). The drift test also assertsGet-InstalledTestAppNamesdispatches the app under its real installed name.32b0d4d1(Subcontracting Test) was installed but never appeared in anyDispatching '...'line in the W1 or US IntegrationTests jobs; no codeunit 149911 header and no test-function output were present. This change makes that app resolve into the dispatch set.Risk & compatibility
projects.json,groups.json,app.json) are changed; this is purely a resolution-logic change inParallelTestExecution.psm1.projects.json key == groups.json name == app.json "name"for every test project, so drift is caught at PR time.