Skip to content

Commit 786e47f

Browse files
committed
Clean out build and update ReadMe
Add a couple of tests to improve coverage
1 parent d76f1ad commit 786e47f

File tree

5 files changed

+200
-59
lines changed

5 files changed

+200
-59
lines changed

ReadMe.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,26 @@ cd Modulebuilder
3232

3333
#### 2. Install dependencies
3434

35-
PowerShellGet has problems updating modules, and the sheer number of parameters needed to do so without errors and warnings is ridiculous, so we use PSDepend. If you don't have PSDepend, _you'll need to install it_ first. Run the `.\bootstrap.ps1` script --it defaults to CurrentUser scope, but has a `-Scope` switch should you want to change it.
35+
We have a few modules which are required for building. They're listed in `RequiredModules.psd1` -- the `.\bootstrap.ps1` script installs them (it defaults to CurrentUser scope, but has a `-Scope` parameter if you're running elevated and want to install them for the `AllUsers`). They only change rarely, so you won't need to run this repeatedly.
3636

3737
```powershell
3838
.\bootstrap.ps1
3939
```
4040

4141
#### 3. Run the `build.ps1` script.
4242

43-
If you want to avoid installing these _additional_ dependencies (i.e. my Configuration module, and Pester 4.4.0+) in your user scope, you can add the `-UseLocalTools` switch to make sure they are only downloaded to a local "Tools" folder.
44-
4543
```powershell
4644
.\build.ps1
4745
```
4846

47+
48+
#### 4. Run tests with Pester
49+
50+
```powershell
51+
Invoke-Pester
52+
```
53+
54+
4955
### What's in the module, so far:
5056

5157
#### `Build-Module`

Tests/Private/InitializeBuild.Tests.ps1

Lines changed: 117 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,35 @@
11
Describe "InitializeBuild" {
2-
Context "It collects the initial data" {
3-
Mock ResolveModuleSource -ModuleName ModuleBuilder { $SourcePath }
4-
Mock ResolveModuleManifest -ModuleName ModuleBuilder { "TestDrive:\Source\MyModule.psd1" }
5-
Mock Push-Location -ModuleName ModuleBuilder {}
6-
Mock Import-Metadata -ModuleName ModuleBuilder { @{Path = "MyModule.psd1"} }
7-
#Mock Update-Object -ModuleName ModuleBuilder { $InputObject }
8-
Mock Get-Variable -ParameterFilter {
9-
$Name -eq "MyInvocation"
10-
} -ModuleName ModuleBuilder {
11-
@{
12-
MyCommand = @{
13-
Parameters = @{
14-
Encoding = @{ParameterType = "string"}
15-
Target = @{ParameterType = "string"}
16-
SourcePath = @{ParameterType = "string"}
17-
SourceDirectories = @{ParameterType = "string[]"}
18-
}
2+
Mock ResolveModuleSource -ModuleName ModuleBuilder { $SourcePath }
3+
Mock ResolveModuleManifest -ModuleName ModuleBuilder { "TestDrive:\Source\MyModule.psd1" }
4+
Mock Push-Location -ModuleName ModuleBuilder {}
5+
Mock Import-Metadata -ModuleName ModuleBuilder { @{Path = "MyModule.psd1"} }
6+
#Mock Update-Object -ModuleName ModuleBuilder { $InputObject }
7+
Mock Get-Variable -ParameterFilter {
8+
$Name -eq "MyInvocation"
9+
} -ModuleName ModuleBuilder {
10+
@{
11+
MyCommand = @{
12+
Parameters = @{
13+
Encoding = @{ParameterType = "string"}
14+
Target = @{ParameterType = "string"}
15+
SourcePath = @{ParameterType = "string"}
16+
SourceDirectories = @{ParameterType = "string[]"}
1917
}
2018
}
2119
}
22-
Mock Get-Module -ModuleName ModuleBuilder {
23-
[PSCustomObject]@{
24-
ModuleBase = "TestDrive:\Source\"
25-
Author = "Test Manager"
26-
Version = [Version]"1.0.0"
27-
Name = "MyModule"
28-
RootModule = "MyModule.psm1"
29-
}
20+
}
21+
Mock Get-Module -ModuleName ModuleBuilder {
22+
[PSCustomObject]@{
23+
ModuleBase = "TestDrive:\Source\"
24+
Author = "Test Manager"
25+
Version = [Version]"1.0.0"
26+
Name = "MyModule"
27+
RootModule = "MyModule.psm1"
3028
}
29+
}
30+
31+
Context "It collects the initial data" {
32+
3133
New-Item "TestDrive:\Source\" -Type Directory
3234

3335
$Result = InModuleScope -ModuleName ModuleBuilder {
@@ -64,4 +66,94 @@ Describe "InitializeBuild" {
6466
$Result.OutputDirectory | Should -be "TestDrive:\1.0.0"
6567
}
6668
}
69+
70+
Context "Invalid module manifest" {
71+
# In the current PowerShell 5.1 and 6.1
72+
# I can't make Get-Module -ListAvailable throw on a manifest
73+
# So I can't test the if($Problems = ... code
74+
}
75+
76+
Context "Build with specified relative output path" {
77+
New-Item "TestDrive:\Source\" -Type Directory
78+
79+
Mock Get-Variable -ModuleName ModuleBuilder {
80+
if($Name -eq "OutputDirectory" -and $ValueOnly) {
81+
".\Output"
82+
}
83+
}
84+
85+
Mock Get-Variable -ParameterFilter {
86+
$Name -eq "MyInvocation" -and $ValueOnly
87+
} -ModuleName ModuleBuilder {
88+
@{
89+
MyCommand = @{
90+
Parameters = @{
91+
Encoding = @{ParameterType = "string"}
92+
Target = @{ParameterType = "string"}
93+
SourcePath = @{ParameterType = "string"}
94+
SourceDirectories = @{ParameterType = "string[]"}
95+
OutputDirectory = @{ParameterType = "string"}
96+
}
97+
}
98+
}
99+
}
100+
101+
$Result = InModuleScope -ModuleName ModuleBuilder {
102+
InitializeBuild -SourcePath TestDrive:\Source\
103+
}
104+
105+
It "Treats the output path as relative to the (parent of the) ModuleSource" {
106+
$Result.ModuleBase | Should -be "TestDrive:\Source\"
107+
$Result.Path | Should -be "TestDrive:\Source\MyModule.psd1"
108+
$Result.OutputDirectory | Should -be "TestDrive:\.\Output"
109+
}
110+
}
111+
112+
113+
114+
115+
Context "Does not fall over if you build from the drive root" {
116+
Mock Get-Variable -ModuleName ModuleBuilder {
117+
if($Name -eq "OutputDirectory" -and $ValueOnly) {
118+
".\Output"
119+
}
120+
}
121+
122+
Mock ResolveModuleManifest -ModuleName ModuleBuilder { "TestDrive:\MyModule.psd1" }
123+
124+
Mock Get-Variable -ParameterFilter {
125+
$Name -eq "MyInvocation" -and $ValueOnly
126+
} -ModuleName ModuleBuilder {
127+
@{
128+
MyCommand = @{
129+
Parameters = @{
130+
Encoding = @{ParameterType = "string"}
131+
Target = @{ParameterType = "string"}
132+
SourcePath = @{ParameterType = "string"}
133+
SourceDirectories = @{ParameterType = "string[]"}
134+
OutputDirectory = @{ParameterType = "string"}
135+
}
136+
}
137+
}
138+
}
139+
140+
Mock Get-Module -ModuleName ModuleBuilder {
141+
[PSCustomObject]@{
142+
ModuleBase = "TestDrive:\"
143+
Author = "Test Manager"
144+
Version = [Version]"1.0.0"
145+
Name = "MyModule"
146+
RootModule = "MyModule.psm1"
147+
}
148+
}
149+
$Result = InModuleScope -ModuleName ModuleBuilder {
150+
InitializeBuild -SourcePath TestDrive:\
151+
}
152+
153+
It "Treats the output path as relative to the (parent of the) ModuleSource" {
154+
$Result.ModuleBase | Should -be "TestDrive:\"
155+
$Result.Path | Should -be "TestDrive:\MyModule.psd1"
156+
$Result.OutputDirectory | Should -be "TestDrive:\.\Output"
157+
}
158+
}
67159
}

Tests/Public/Build-Module.Tests.ps1

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,69 @@ Describe "Build-Module" {
120120
}
121121
}
122122
}
123+
124+
Context "When run without 'Clean' in the target" {
125+
Push-Location TestDrive:\ -StackName BuildModuleTest
126+
New-Item -ItemType Directory -Path TestDrive:\MyModule\Public -Force
127+
New-Item -ItemType File -Path TestDrive:\MyModule\Public\Get-MyInfo.ps1 -Force
128+
Start-Sleep -Milliseconds 200 # to ensure the output is after the input
129+
New-Item -ItemType Directory -Path TestDrive:\1.0.0\ -Force
130+
New-Item -ItemType File -Path TestDrive:\1.0.0\MyModule.psm1 -Force
131+
132+
Mock SetModuleContent -ModuleName ModuleBuilder {}
133+
Mock Update-Metadata -ModuleName ModuleBuilder {}
134+
Mock InitializeBuild -ModuleName ModuleBuilder {
135+
# These are actually all the values that we need
136+
@{
137+
OutputDirectory = "TestDrive:\1.0.0"
138+
Name = "MyModule"
139+
ModuleBase = "TestDrive:\MyModule\"
140+
CopyDirectories = @()
141+
Encoding = "UTF8"
142+
PublicFilter = "Public\*.ps1"
143+
}
144+
}
145+
146+
Mock Test-Path {$True} -Parameter {$Path -eq "TestDrive:\1.0.0"} -ModuleName ModuleBuilder
147+
Mock Remove-Item {} -Parameter {$Path -eq "TestDrive:\1.0.0"} -ModuleName ModuleBuilder
148+
Mock Set-Location {} -ModuleName ModuleBuilder
149+
Mock Copy-Item {} -ModuleName ModuleBuilder
150+
151+
Mock Get-ChildItem {
152+
[IO.FileInfo]$(Join-Path $(Convert-Path "TestDrive:\") "MyModule\Public\Get-MyInfo.ps1")
153+
} -ModuleName ModuleBuilder
154+
155+
Mock Get-Item {
156+
[PSCustomObject]@{ LastWriteTime = Get-Date }
157+
} -ModuleName ModuleBuilder
158+
159+
Mock New-Item {} -Parameter {
160+
$Path -eq "TestDrive:\1.0.0" -and
161+
$ItemType -eq "Directory" -and
162+
$Force -eq $true
163+
} -ModuleName ModuleBuilder
164+
165+
try {
166+
Build-Module -Target Build
167+
} finally {
168+
Pop-Location -StackName BuildModuleTest
169+
}
170+
171+
# NOTE: We're not just clearing output, but the whole folder
172+
It "Should NOT remove the output folder" {
173+
Assert-MockCalled Remove-Item -ModuleName ModuleBuilder -Times 0
174+
}
175+
176+
It "Should check the dates on the output" {
177+
Assert-MockCalled Get-Item -ModuleName ModuleBuilder -Times 1
178+
}
179+
180+
It "Should not (re)create the OutputDirectory" {
181+
Assert-MockCalled New-Item -ModuleName ModuleBuilder -Times 0
182+
}
183+
184+
It "Should not rebuild the source files" {
185+
Assert-MockCalled SetModuleContent -ModuleName ModuleBuilder -Times 0
186+
}
187+
}
123188
}

build.depend.psd1

Lines changed: 0 additions & 9 deletions
This file was deleted.

build.ps1

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,24 @@
1+
#requires -Module Configuration
2+
<#
3+
.Synopsis
4+
This is just a bootstrapping build, for when ModuleBuilder can't be used to build ModuleBuilder
5+
#>
16
[CmdletBinding()]
27
param(
8+
# A specific folder to build into
39
$OutputDirectory,
410

511
# The version of the output module
612
[Alias("ModuleVersion")]
7-
[version]$Version,
8-
9-
$Repository = 'PSGallery',
10-
11-
[ValidateSet("CurrentUser", "AllUsers", "LocalTools")]
12-
$InstallToolScope = "CurrentUser",
13-
14-
[switch]$Test
13+
[version]$Version
1514
)
1615

1716
# Sanitize parameters to pass to Build-Module
18-
$null = $PSBoundParameters.Remove('Repository')
1917
$null = $PSBoundParameters.Remove('Test')
20-
$null = $PSBoundParameters.Remove('InstallToolScope')
2118

2219
$ErrorActionPreference = "Stop"
2320
Push-Location $PSScriptRoot -StackName BuildBuildModule
2421
try {
25-
Import-Module Configuration
2622

2723
# Build ModuleBuilder with ModuleBuilder:
2824
Write-Verbose "Compiling ModuleBuilderBootstrap module"
@@ -42,17 +38,8 @@ try {
4238
ModuleBuilderBootstrap\Build-Module Source\build.psd1 @PSBoundParameters -Target CleanBuild -Passthru -OutVariable BuildOutput | Split-Path
4339
Write-Verbose "Module build output in $(Split-Path $BuildOutput.Path)"
4440

45-
# Test module
46-
if($Test) {
47-
Write-Verbose "Invoke-Pester after importing $($BuildOutput.Path)" -Verbose
48-
Remove-Module ModuleBuilderBootstrap, ModuleBuilder -ErrorAction SilentlyContinue -Verbose:$false
49-
Import-Module $BuildOutput.Path -Verbose:$false -DisableNameChecking
50-
Invoke-Pester -CodeCoverage (Join-Path $BuildOutput.ModuleBase $BuildOutput.RootModule) -PassThru |
51-
Convert-CodeCoverage -SourceRoot .\Source -Relative
52-
}
53-
54-
# Clean up environment after tests
55-
Remove-Module ModuleBuilderBootStrap, ModuleBuilder -ErrorAction SilentlyContinue -Verbose:$false
41+
# Clean up environment
42+
Remove-Module ModuleBuilderBootStrap -ErrorAction SilentlyContinue -Verbose:$false
5643

5744
} finally {
5845
Pop-Location -StackName BuildBuildModule

0 commit comments

Comments
 (0)