🩹 [Patch]: Framework-generated boilerplate code now tested and covered#113
Conversation
…, and OnRemove cleanup
There was a problem hiding this comment.
Pull request overview
Adds Pester coverage for framework-injected boilerplate in compiled modules so module authors’ coverage reports aren’t penalized for generated code.
Changes:
- Reads the compiled
.psm1to detect the class-exporter boilerplate and extract expected public class/enum names. - Adds Pester contexts to validate
$IsWindowsavailability, type accelerator registration, andOnRemovecleanup behavior. - Forces module import during the “importable” test to ensure reloading.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… class exporter" This reverts commit c694fad.
…s, try/finally in OnRemove
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…lity Pester v5 evaluates -Skip and -ForEach during the Discovery phase, but BeforeAll only runs during the Run phase. This caused hasClassExporter, expectedClassNames, and expectedEnumNames to be null during discovery, skipping all framework type-accelerator tests. Move the module content reading and regex extraction to the top-level script scope so the variables are available when Pester discovers tests.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Pester v5 script-scope variables are visible during Discovery (for -Skip and -ForEach) but not inside It blocks during the Run phase. Add a BeforeAll inside the Describe block that re-exposes the discovery variables so It blocks can reference moduleName, moduleManifestPath, etc. Also fix Context blocks that were incorrectly renamed to Get-Context.
Pester v5 Discovery and Run are separate executions. Script-level variables set during Discovery do not exist during Run, so referencing them via $script: in a Describe BeforeAll yields null. Replace the Describe-level BeforeAll bridge with a top-level BeforeAll that recomputes all variables from $Path, which Pester re-passes via container data to both phases.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The $IsWindows PS 5.1 shim is being removed from Build-PSModule since PSModule targets PowerShell LTS (7.6+). Remove the corresponding test context and update the test repo output fixture.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ion, fix fixture comment
…le authors (#310) Framework-generated boilerplate — type accelerator registration and `OnRemove` cleanup — is now tested and covered by updated action versions referenced in this workflow. The obsolete `$IsWindows` PS 5.1 shim is no longer injected into built modules. Coverage from the framework test step and the module test step is already aggregated by Get-CodeCoverage, so module authors' coverage percentages now reflect only the code they wrote. - Fixes #309 ## Changed: Build-PSModule updated to v4.0.14 Built modules no longer include the `$IsWindows = $true` Desktop edition shim or its PSScriptAnalyzer suppression attributes. PSModule targets PowerShell LTS (7.6+), where `$IsWindows` is a built-in automatic variable. See [PSModule/Build-PSModule#132](PSModule/Build-PSModule#132) for details. ## Changed: Test-PSModule updated to v3.0.10 The framework module tests now validate that every public class and enum is registered as a type accelerator after import, and that the `OnRemove` hook cleans them up when the module is removed. These tests produce coverage artifacts that are aggregated with module author test coverage, so framework-generated boilerplate no longer counts against the module author's coverage target. See [PSModule/Test-PSModule#113](PSModule/Test-PSModule#113) for details. ## Changed: README documents the framework testing design The README now explains: - Why framework-generated code is tested by the framework itself - How coverage from both the framework test step and the module test step is aggregated - That module authors do not need to test framework-generated code themselves ## Technical Details - `.github/workflows/Build-Module.yml`: Updated Build-PSModule from v4.0.13 to v4.0.14 (`345728124d201f371a8b0f1aacb98f89000a06dc`) - `.github/workflows/Test-Module.yml`: Updated Test-PSModule from v3.0.8 to v3.0.10 (`8c3337136dc7cf320da39eeb50e776d04bc9ac73`) - `.github/workflows/Test-SourceCode.yml`: Updated Test-PSModule from v3.0.8 to v3.0.10 - `README.md`: Added "Code coverage for framework-generated code" paragraph under the Framework test section; added coverage aggregation details under the Get code coverage section; removed reference to the `$IsWindows` shim - No workflow structure changes — code coverage was already enabled in Test-Module.yml and Get-PesterCodeCoverage already aggregates all `*-CodeCoverage` artifacts
Module tests now validate framework-injected boilerplate — type accelerator registration and OnRemove cleanup — so code coverage reflects actual test gaps instead of penalizing module authors for untested framework code.
New: Type accelerator registration tests
When
Build-PSModuleinjects a class exporter region, the module tests now verify that every public class and enum listed in$ExportableClasses/$ExportableEnumsis registered as a type accelerator after import.Modules without a class exporter region skip these tests automatically.
New: OnRemove cleanup tests
A new test verifies that when the module is removed, its type accelerators are cleaned up via the
OnRemovehook — preventing type collisions when re-importing or importing a different version.Changed: IsWindows compatibility shim removed
The
$IsWindows = $truePS 5.1 Desktop edition shim has been removed fromBuild-PSModule(see PSModule/Build-PSModule#132). The corresponding test context and test fixture output have been removed here as well. PSModule targets PowerShell LTS (7.6+) where$IsWindowsis a built-in automatic variable.Technical Details
PSModule.Tests.ps1: Discovery-phase variables ($hasClassExporter,$expectedClassNames,$expectedEnumNames) are computed at script scope for Pester's-Skip/-ForEachevaluation, then recomputed in a top-levelBeforeAllfor the Run phase. This dual-computation pattern is required because Pester v5 Discovery and Run are separate executions that don't share script-scope state.PSModuleTest.psm1(test fixture): Updated to remove the$IsWindowsshim and its suppression attributes, matching the new Build-PSModule output format.PSUseDeclaredVarsMoreThanAssignmentssuppressed at file level because the analyzer cannot trace variable flow across Pester'sBeforeAll→Itblock boundaries.