Skip to content

Commit 6a07a67

Browse files
tablackburnclaude
andauthored
refactor(tests): bootstrap remaining standalone tests via build.ps1 (#39)
* refactor(tests): bootstrap remaining standalone tests via build.ps1 Apply the delegate-to-build.ps1 bootstrap from #38 to the rest of the test scaffolds: tests/Manifest.tests.ps1 (both BeforeDiscovery and BeforeAll) and the tests/Unit/ Private and Public templates. These previously called Invoke-psake against build.psake.ps1 directly without populating the BuildHelpers env vars its properties block needs, so the standalone path was broken the same way Help.tests.ps1 was. Each guard now calls build.ps1 -Task 'Build' -Bootstrap via the call operator (&), so dependency bootstrap and BuildHelpers environment setup run through the canonical entry point and the script's terminating exit is contained to the script boundary instead of ending the Pester run. Project root is resolved with Split-Path -Parent (one level for Manifest.tests.ps1, three for the tests/Unit/ files, matching each file's existing root computation) and a single two-argument Join-Path, keeping it valid on PowerShell 5.1. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(tests): compute project root once in bootstrap Address review feedback (Copilot) on the standalone bootstrap: the project root was computed twice -- once inline for $buildScript and again a few lines later for $projectRoot -- which is exactly the kind of duplication that can drift. Hoist the single $projectRoot assignment above the BHBuildOutput guard and derive $buildScript from it via Join-Path, in Manifest.tests.ps1 (both blocks) and the tests/Unit/ Private and Public templates. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent fc04e67 commit 6a07a67

4 files changed

Lines changed: 53 additions & 28 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ own `CHANGELOG.md` (generated from `CHANGELOG.template.md` during init).
2020

2121
- Renamed required PowerShell Gallery publish secret `PS_GALLERY_KEY``PSGALLERY_API_KEY` so the secret name matches the env var name PowerShellBuild reads (eliminating the previous mapping caveat). New modules created from the template after this change pick up the new name automatically. **Migration for existing modules:** create a new `PSGALLERY_API_KEY` repo secret with the same value, update `.github/workflows/PublishModuleToPowerShellGallery.yaml` to reference `secrets.PSGALLERY_API_KEY`, then delete the old `PS_GALLERY_KEY` secret.
2222
- Test scaffolding (`tests/Help.tests.ps1`, `tests/Manifest.tests.ps1`, `tests/Meta.tests.ps1`, `tests/MetaFixers.psm1`, and the `tests/Unit/` templates) no longer names parameters on single-argument calls (e.g. `Test-Path $path`, `Get-Module $name`, `Get-Help $command`), matching the scoped named-parameter rule — name parameters only when a call passes two or more arguments. A trailing switch counts as an argument, so `Split-Path -Path $x -Parent`, `Get-Content -Path $x -Raw`, and `Get-ChildItem -Path $x -Recurse` keep their names, as do genuinely multi-value calls (`Join-Path`, `Get-Command -Name … -CommandType …`) and `Test-Path -LiteralPath`.
23+
- `tests/Manifest.tests.ps1` and the `tests/Unit/` templates now use the same standalone build-bootstrap approach introduced for `tests/Help.tests.ps1` (#38): their `BHBuildOutput`-missing guards delegate to `build.ps1 -Task 'Build' -Bootstrap` (invoked with `&`, not dot-sourced, so its terminating `exit` is contained) instead of calling `Invoke-psake` against `build.psake.ps1` directly. This routes dependency bootstrap and BuildHelpers environment setup through the canonical entry point, so these tests can be run standalone (e.g. from an editor or by an agent) without first running `./build.ps1`. No effect on CI or `./build.ps1` runs — the guard only fires when `BHBuildOutput` is unset.
2324

2425
## [2026.04.29] - 2026-04-29
2526

tests/Manifest.tests.ps1

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,19 +57,25 @@
5757
param()
5858

5959
BeforeDiscovery {
60+
# Resolve the project root once (tests/ -> repo root); used both to locate
61+
# build.ps1 below and to compute the staged build output path.
62+
$projectRoot = Split-Path -Path $PSScriptRoot -Parent
63+
6064
# Check if the BHBuildOutput environment variable exists to determine if this test is running in a psake
6165
# build or not. If it does not exist, it is not running in a psake build, so build the module.
6266
if ($null -eq $Env:BHBuildOutput) {
63-
$buildFilePath = Join-Path -Path $PSScriptRoot -ChildPath '..\build.psake.ps1'
64-
$invokePsakeParameters = @{
65-
TaskList = 'Build'
66-
BuildFile = $buildFilePath
67-
}
68-
Invoke-psake @invokePsakeParameters
67+
# Standalone run (e.g. Invoke-Pester on this file directly, or an agent
68+
# running one test): the module isn't built and the BuildHelpers env vars
69+
# aren't set. Defer to build.ps1 -- the canonical entry point -- to bootstrap
70+
# dependencies, set the BuildHelpers environment, and stage the module.
71+
# Invoke with & (not dot-sourcing): build.ps1 ends in an exit statement, and
72+
# the call operator contains it to the script boundary instead of ending the
73+
# whole Pester run.
74+
$buildScript = Join-Path -Path $projectRoot -ChildPath 'build.ps1'
75+
& $buildScript -Task 'Build' -Bootstrap
6976
}
7077

7178
# PowerShellBuild outputs to Output/<ModuleName>/<Version>/, override BHBuildOutput
72-
$projectRoot = Split-Path -Path $PSScriptRoot -Parent
7379
$sourceManifest = Join-Path -Path $projectRoot -ChildPath "$Env:BHProjectName/$Env:BHProjectName.psd1"
7480
$moduleVersion = (Import-PowerShellDataFile $sourceManifest).ModuleVersion
7581
$Env:BHBuildOutput = Join-Path -Path $projectRoot -ChildPath "Output/$Env:BHProjectName/$moduleVersion"
@@ -96,19 +102,25 @@ BeforeDiscovery {
96102
$isTemplate = Test-Path -LiteralPath (Join-Path -Path $Env:BHProjectPath -ChildPath 'CHANGELOG.template.md')
97103
}
98104
BeforeAll {
105+
# Resolve the project root once (tests/ -> repo root); used both to locate
106+
# build.ps1 below and to compute the staged build output path.
107+
$projectRoot = Split-Path -Path $PSScriptRoot -Parent
108+
99109
# Check if the BHBuildOutput environment variable exists to determine if this test is running in a psake
100110
# build or not. If it does not exist, it is not running in a psake build, so build the module.
101111
if ($null -eq $Env:BHBuildOutput) {
102-
$buildFilePath = Join-Path -Path $PSScriptRoot -ChildPath '..\build.psake.ps1'
103-
$invokePsakeParameters = @{
104-
TaskList = 'Build'
105-
BuildFile = $buildFilePath
106-
}
107-
Invoke-psake @invokePsakeParameters
112+
# Standalone run (e.g. Invoke-Pester on this file directly, or an agent
113+
# running one test): the module isn't built and the BuildHelpers env vars
114+
# aren't set. Defer to build.ps1 -- the canonical entry point -- to bootstrap
115+
# dependencies, set the BuildHelpers environment, and stage the module.
116+
# Invoke with & (not dot-sourcing): build.ps1 ends in an exit statement, and
117+
# the call operator contains it to the script boundary instead of ending the
118+
# whole Pester run.
119+
$buildScript = Join-Path -Path $projectRoot -ChildPath 'build.ps1'
120+
& $buildScript -Task 'Build' -Bootstrap
108121
}
109122

110123
# PowerShellBuild outputs to Output/<ModuleName>/<Version>/, override BHBuildOutput
111-
$projectRoot = Split-Path -Path $PSScriptRoot -Parent
112124
$sourceManifest = Join-Path -Path $projectRoot -ChildPath "$Env:BHProjectName/$Env:BHProjectName.psd1"
113125
$moduleVersion = (Import-PowerShellDataFile $sourceManifest).ModuleVersion
114126
$Env:BHBuildOutput = Join-Path -Path $projectRoot -ChildPath "Output/$Env:BHProjectName/$moduleVersion"

tests/Unit/Private/Invoke-{{Prefix}}Helper.tests.ps1

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,24 @@
66
param()
77

88
BeforeDiscovery {
9+
# Resolve the project root once (tests/Unit/<Layer>/ -> repo root, three levels up);
10+
# used both to locate build.ps1 below and to compute the staged build output path.
11+
$projectRoot = Split-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -Parent
12+
913
# Build module if not running in psake build
1014
if ($null -eq $Env:BHBuildOutput) {
11-
$buildFilePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\..\build.psake.ps1'
12-
$invokePsakeParameters = @{
13-
TaskList = 'Build'
14-
BuildFile = $buildFilePath
15-
}
16-
Invoke-psake @invokePsakeParameters
15+
# Standalone run (e.g. Invoke-Pester on this file directly, or an agent
16+
# running one test): the module isn't built and the BuildHelpers env vars
17+
# aren't set. Defer to build.ps1 -- the canonical entry point -- to bootstrap
18+
# dependencies, set the BuildHelpers environment, and stage the module.
19+
# Invoke with & (not dot-sourcing): build.ps1 ends in an exit statement, and
20+
# the call operator contains it to the script boundary instead of ending the
21+
# whole Pester run.
22+
$buildScript = Join-Path -Path $projectRoot -ChildPath 'build.ps1'
23+
& $buildScript -Task 'Build' -Bootstrap
1724
}
1825

1926
# PowerShellBuild outputs to Output/<ModuleName>/<Version>/
20-
$projectRoot = Split-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -Parent
2127
$sourceManifest = Join-Path -Path $projectRoot -ChildPath "$Env:BHProjectName/$Env:BHProjectName.psd1"
2228
$moduleVersion = (Import-PowerShellDataFile $sourceManifest).ModuleVersion
2329
$Env:BHBuildOutput = Join-Path -Path $projectRoot -ChildPath "Output/$Env:BHProjectName/$moduleVersion"

tests/Unit/Public/Get-{{Prefix}}Example.tests.ps1

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,24 @@
66
param()
77

88
BeforeDiscovery {
9+
# Resolve the project root once (tests/Unit/<Layer>/ -> repo root, three levels up);
10+
# used both to locate build.ps1 below and to compute the staged build output path.
11+
$projectRoot = Split-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -Parent
12+
913
# Build module if not running in psake build
1014
if ($null -eq $Env:BHBuildOutput) {
11-
$buildFilePath = Join-Path -Path $PSScriptRoot -ChildPath '..\..\..\build.psake.ps1'
12-
$invokePsakeParameters = @{
13-
TaskList = 'Build'
14-
BuildFile = $buildFilePath
15-
}
16-
Invoke-psake @invokePsakeParameters
15+
# Standalone run (e.g. Invoke-Pester on this file directly, or an agent
16+
# running one test): the module isn't built and the BuildHelpers env vars
17+
# aren't set. Defer to build.ps1 -- the canonical entry point -- to bootstrap
18+
# dependencies, set the BuildHelpers environment, and stage the module.
19+
# Invoke with & (not dot-sourcing): build.ps1 ends in an exit statement, and
20+
# the call operator contains it to the script boundary instead of ending the
21+
# whole Pester run.
22+
$buildScript = Join-Path -Path $projectRoot -ChildPath 'build.ps1'
23+
& $buildScript -Task 'Build' -Bootstrap
1724
}
1825

1926
# PowerShellBuild outputs to Output/<ModuleName>/<Version>/
20-
$projectRoot = Split-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -Parent
2127
$sourceManifest = Join-Path -Path $projectRoot -ChildPath "$Env:BHProjectName/$Env:BHProjectName.psd1"
2228
$moduleVersion = (Import-PowerShellDataFile $sourceManifest).ModuleVersion
2329
$Env:BHBuildOutput = Join-Path -Path $projectRoot -ChildPath "Output/$Env:BHProjectName/$moduleVersion"

0 commit comments

Comments
 (0)