Skip to content

🩹 [Patch]: Framework-generated boilerplate code now tested and covered#113

Merged
Marius Storhaug (MariusStorhaug) merged 13 commits intomainfrom
feature/framework-boilerplate-tests
Apr 5, 2026
Merged

🩹 [Patch]: Framework-generated boilerplate code now tested and covered#113
Marius Storhaug (MariusStorhaug) merged 13 commits intomainfrom
feature/framework-boilerplate-tests

Conversation

@MariusStorhaug
Copy link
Copy Markdown
Member

@MariusStorhaug Marius Storhaug (MariusStorhaug) commented Apr 5, 2026

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-PSModule injects a class exporter region, the module tests now verify that every public class and enum listed in $ExportableClasses / $ExportableEnums is registered as a type accelerator after import.

Context Framework - Type accelerator registration
  [+] Should register public class [Book] as a type accelerator
  [+] Should register public class [BookList] as a type accelerator

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 OnRemove hook — preventing type collisions when re-importing or importing a different version.

Context Framework - Module OnRemove cleanup
  [+] Should clean up type accelerators when the module is removed

Changed: IsWindows compatibility shim removed

The $IsWindows = $true PS 5.1 Desktop edition shim has been removed from Build-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 $IsWindows is 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/-ForEach evaluation, then recomputed in a top-level BeforeAll for 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 $IsWindows shim and its suppression attributes, matching the new Build-PSModule output format.
  • PSScriptAnalyzer PSUseDeclaredVarsMoreThanAssignments suppressed at file level because the analyzer cannot trace variable flow across Pester's BeforeAllIt block boundaries.

@MariusStorhaug Marius Storhaug (MariusStorhaug) marked this pull request as ready for review April 5, 2026 12:52
Copilot AI review requested due to automatic review settings April 5, 2026 12:52
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 .psm1 to detect the class-exporter boilerplate and extract expected public class/enum names.
  • Adds Pester contexts to validate $IsWindows availability, type accelerator registration, and OnRemove cleanup 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.

Copilot AI review requested due to automatic review settings April 5, 2026 13:08
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.
Copilot AI review requested due to automatic review settings April 5, 2026 13:37
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.
Copilot AI review requested due to automatic review settings April 5, 2026 14:32
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.
Copilot AI review requested due to automatic review settings April 5, 2026 15:49
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.

@MariusStorhaug Marius Storhaug (MariusStorhaug) merged commit 8c33371 into main Apr 5, 2026
26 checks passed
@MariusStorhaug Marius Storhaug (MariusStorhaug) deleted the feature/framework-boilerplate-tests branch April 5, 2026 16:32
Marius Storhaug (MariusStorhaug) added a commit to PSModule/Process-PSModule that referenced this pull request Apr 5, 2026
…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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants