Skip to content

Commit 60887fd

Browse files
committed
update so tests can be run on mac with powershell
1 parent 8e78b5f commit 60887fd

7 files changed

Lines changed: 238 additions & 73 deletions
Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1+
param(
2+
[string] $Filter = "*"
3+
)
4+
15
$ErrorActionPreference = "Stop";
26
Set-StrictMode -Version "Latest";
37

48
$thisScript = $MyInvocation.MyCommand.Path;
59
$thisFolder = [System.IO.Path]::GetDirectoryName($thisScript);
610
$rootFolder = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($thisFolder, "..", "..")); # Adjust to always point to the root
7-
$testFiles = Get-ChildItem -Path "$thisFolder" -Filter "*.tests.ps1" -Recurse
11+
$sharedRunner = Join-Path $rootFolder "tools" "Invoke-SharedPesterTests.ps1"
812

913
function Unpack-Scripts-Under-Test {
14+
$testFiles = Get-ChildItem -Path "$thisFolder" -Filter "*.tests.ps1" -Recurse
15+
1016
foreach ($testFile in $testFiles) {
1117
$baseName = $testFile.BaseName -replace "\.ScriptBody.Tests$"
1218
$scriptFileName = "$baseName.ScriptBody.ps1"
@@ -35,28 +41,8 @@ function Unpack-Scripts-Under-Test {
3541
}
3642
}
3743

38-
function Import-Pester {
39-
# Attempt to use local Pester module, fallback to global if not found
40-
try {
41-
$packagesFolder = [System.IO.Path]::Combine($rootFolder, "packages")
42-
$pester3Path = [System.IO.Path]::Combine($packagesFolder, "Pester\tools\Pester")
43-
# Import the specific version of Pester 3.4.0
44-
Import-Module -Name $pester3Path -RequiredVersion 3.4.0 -ErrorAction Stop
45-
} catch {
46-
Write-Host "Using globally installed Pester module version 3.4.0."
47-
# Specify the exact version of Pester 3.x you have installed
48-
Import-Module -Name Pester -RequiredVersion 3.4.0 -ErrorAction Stop
49-
}
50-
}
51-
52-
function Run-Tests {
53-
# Find and run all Pester test files in the tests directory
54-
foreach ($testFile in $testFiles) {
55-
Write-Host "Running tests in: $($testFile.FullName)"
56-
Invoke-Pester -Path $testFile.FullName
57-
}
58-
}
59-
60-
Import-Pester
61-
Unpack-Scripts-Under-Test
62-
Run-Tests
44+
& $sharedRunner `
45+
-TestRoot $thisFolder `
46+
-Filter $Filter `
47+
-BeforeRun ${function:Unpack-Scripts-Under-Test} `
48+
-UsePassThruFailureCheck

step-templates/tests/sql-backup-database.ScriptBody.Tests.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
$ErrorActionPreference = "Stop";
22
Set-StrictMode -Version "Latest";
33

4-
. "$PSScriptRoot\..\sql-backup-database.ScriptBody.ps1"
4+
. (Join-Path $PSScriptRoot ".." "sql-backup-database.ScriptBody.ps1")
55

66
function SetupTestEnvironment {
77
param(
@@ -79,7 +79,7 @@ function SetupTestEnvironment {
7979
Describe "ApplyRetentionPolicy Tests" {
8080

8181
BeforeAll {
82-
$script:BackupDirectory = "C:\Backups"
82+
$script:BackupDirectory = Join-Path ([System.IO.Path]::GetTempPath()) "OctopusDeployLibrary-SqlBackupTests"
8383
$script:DatabaseName = "ExampleDB"
8484
$script:StartDate = Get-Date
8585
$script:timestampFormat = "yyyy-MM-dd-HHmmss"

step-templates/tests/windows-scheduled-task-create.ScriptBody.Tests.ps1

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
$ErrorActionPreference = "Stop";
22
Set-StrictMode -Version "Latest";
33

4-
. "$PSScriptRoot\..\windows-scheduled-task-create.ScriptBody.ps1"
4+
. (Join-Path $PSScriptRoot ".." "windows-scheduled-task-create.ScriptBody.ps1")
55

66
Describe "Create-ScheduledTask" {
77

@@ -12,8 +12,8 @@ Describe "Create-ScheduledTask" {
1212
It "Should invoke a matching command line" {
1313
Create-ScheduledTask;
1414
Assert-MockCalled Invoke-CommandLine -Times 1 -ParameterFilter {
15-
$expectedCmd = "C:\Windows\System32\schtasks.exe"
16-
$expectedArgs = @( "/Create", "/RU", "", "/SC", "", "/TN", "`"`"", "/TR", "''", "/F" )
15+
$expectedCmd = "$($env:SystemRoot)\System32\schtasks.exe"
16+
$expectedArgs = @( "/Create", "/RU", "`"`"", "/SC", "", "/TN", "`"`"", "/TR", "`"''`"", "/F" )
1717
$argDiffs = Compare-Object $ArgumentList $expectedArgs -SyncWindow 0;
1818
#Write-Host ("expected = " + ($expectedArgs | % { "[$($_)]"}));
1919
#Write-Host ("actual = " + ($ArgumentList | % { "[$($_)]"}));
@@ -39,8 +39,8 @@ Describe "Create-ScheduledTask" {
3939
-Duration "" `
4040
-StartNewTaskNow "";
4141
Assert-MockCalled Invoke-CommandLine -Times 1 -ParameterFilter {
42-
$expectedCmd = "C:\Windows\System32\schtasks.exe"
43-
$expectedArgs = @( "/Create", "/RU", "", "/SC", "", "/TN", "`"`"", "/TR", "''", "/F" )
42+
$expectedCmd = "$($env:SystemRoot)\System32\schtasks.exe"
43+
$expectedArgs = @( "/Create", "/RU", "`"`"", "/SC", "", "/TN", "`"`"", "/TR", "`"''`"", "/F" )
4444
$argDiffs = Compare-Object $ArgumentList $expectedArgs -SyncWindow 0;
4545
#Write-Host ("expected = " + ($expectedArgs | % { "[$($_)]"}));
4646
#Write-Host ("actual = " + ($ArgumentList | % { "[$($_)]"}));
@@ -66,8 +66,8 @@ Describe "Create-ScheduledTask" {
6666
-Duration "myDuration"`
6767
-StartNewTaskNow "myStartNewTaskNow";
6868
Assert-MockCalled Invoke-CommandLine -Times 1 -ParameterFilter {
69-
$expectedCmd = "C:\Windows\System32\schtasks.exe"
70-
$expectedArgs = @( "/Create", "/RU", "myRunAsUser", "/RP", "myRunAsPassword", "/SC", "mySchedule", "/D", "myDays", "/TN", "`"myTaskname`"", "/TR", "`"'myTaskRun' 'myArguments'`"", "/ST", "myStartTime", "/DU", "myDuration", "/SD", "myStartDate", "/F", "/RL", "HIGHEST" )
69+
$expectedCmd = "$($env:SystemRoot)\System32\schtasks.exe"
70+
$expectedArgs = @( "/Create", "/RU", "`"myRunAsUser`"", "/RP `"myRunAsPassword`"", "/SC", "mySchedule", "/RI", "myInterval", "/D", "myDays", "/TN", "`"myTaskName`"", "/TR", "`"'myTaskRun' myArguments`"", "/ST", "myStartTime", "/DU", "myDuration", "/SD", "myStartDate", "/F", "/RL", "HIGHEST" )
7171
$argDiffs = Compare-Object $ArgumentList $expectedArgs -SyncWindow 0;
7272
#Write-Host ("expected = " + ($expectedArgs | % { "[$($_)]"}));
7373
#Write-Host ("actual = " + ($ArgumentList | % { "[$($_)]"}));
@@ -93,8 +93,8 @@ Describe "Create-ScheduledTask" {
9393
-Duration "" `
9494
-StartNewTaskNow "";
9595
Assert-MockCalled Invoke-CommandLine -Times 1 -ParameterFilter {
96-
$expectedCmd = "C:\Windows\System32\schtasks.exe"
97-
$expectedArgs = @( "/Create", "/RU", "", "/SC", "", "/TN", "`"`"", "/TR", "'myTaskRun'", "/F" )
96+
$expectedCmd = "$($env:SystemRoot)\System32\schtasks.exe"
97+
$expectedArgs = @( "/Create", "/RU", "`"`"", "/SC", "", "/TN", "`"`"", "/TR", "`"'myTaskRun'`"", "/F" )
9898
$argDiffs = Compare-Object $ArgumentList $expectedArgs -SyncWindow 0;
9999
#Write-Host ("expected = " + ($expectedArgs | % { "[$($_)]"}));
100100
#Write-Host ("actual = " + ($ArgumentList | % { "[$($_)]"}));
@@ -120,8 +120,8 @@ Describe "Create-ScheduledTask" {
120120
-Duration "" `
121121
-StartNewTaskNow "";
122122
Assert-MockCalled Invoke-CommandLine -Times 1 -ParameterFilter {
123-
$expectedCmd = "C:\Windows\System32\schtasks.exe"
124-
$expectedArgs = @( "/Create", "/RU", "", "/SC", "", "/TN", "`"`"", "/TR", "`"'myTaskRun' 'myArguments'`"", "/F" )
123+
$expectedCmd = "$($env:SystemRoot)\System32\schtasks.exe"
124+
$expectedArgs = @( "/Create", "/RU", "`"`"", "/SC", "", "/TN", "`"`"", "/TR", "`"'myTaskRun' myArguments`"", "/F" )
125125
$argDiffs = Compare-Object $ArgumentList $expectedArgs -SyncWindow 0;
126126
#Write-Host ("expected = " + ($expectedArgs | % { "[$($_)]"}));
127127
#Write-Host ("actual = " + ($ArgumentList | % { "[$($_)]"}));
@@ -132,7 +132,7 @@ Describe "Create-ScheduledTask" {
132132
}
133133

134134
Context "WEEKDAYS schedule parameter specified" {
135-
It "WEEKDAYS gets replaced with WEEKLY" {
135+
It "WEEKDAYS is passed through when no days are specified" {
136136
Create-ScheduledTask -TaskName "" `
137137
-RunAsUser "" `
138138
-RunAsPassword "" `
@@ -147,8 +147,8 @@ Describe "Create-ScheduledTask" {
147147
-Duration "" `
148148
-StartNewTaskNow "";
149149
Assert-MockCalled Invoke-CommandLine -Times 1 -ParameterFilter {
150-
$expectedCmd = "C:\Windows\System32\schtasks.exe"
151-
$expectedArgs = @( "/Create", "/RU", "", "/SC", "WEEKLY", "/TN", "`"`"", "/TR", "''", "/D", "MON,TUE,WED,THU,FRI", "/F" )
150+
$expectedCmd = "$($env:SystemRoot)\System32\schtasks.exe"
151+
$expectedArgs = @( "/Create", "/RU", "`"`"", "/SC", "WEEKDAYS", "/TN", "`"`"", "/TR", "`"''`"", "/F" )
152152
$argDiffs = Compare-Object $ArgumentList $expectedArgs -SyncWindow 0;
153153
Write-Host ("expected = " + ($expectedArgs | % { "[$($_)]"}));
154154
Write-Host ("actual = " + ($ArgumentList | % { "[$($_)]"}));

tools/Invoke-SharedPesterTests.ps1

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
param(
2+
[Parameter(Mandatory = $true)]
3+
[string] $TestRoot,
4+
[string] $Filter = "*",
5+
[scriptblock] $BeforeRun,
6+
[string[]] $ImportModules = @(),
7+
[switch] $UsePassThruFailureCheck
8+
)
9+
10+
$ErrorActionPreference = "Stop";
11+
Set-StrictMode -Version "Latest";
12+
13+
$testRootPath = [System.IO.Path]::GetFullPath($TestRoot)
14+
$repoRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot ".."))
15+
$originalSystemRoot = $env:SystemRoot
16+
$originalTemp = $env:TEMP
17+
18+
function Get-PesterModulePath {
19+
$packagesFolder = Join-Path $repoRoot "packages"
20+
$localPesterPaths = @(
21+
(Join-Path $packagesFolder "Pester" "tools" "Pester"),
22+
(Join-Path $packagesFolder "Pester.3.4.3" "tools" "Pester")
23+
)
24+
25+
foreach ($localPesterPath in $localPesterPaths) {
26+
if (Test-Path -Path $localPesterPath) {
27+
return $localPesterPath
28+
}
29+
}
30+
31+
$globalPester = Get-Module -ListAvailable Pester | Where-Object { $_.Version -eq [version]"3.4.3" } | Select-Object -First 1
32+
if ($globalPester) {
33+
return $globalPester.ModuleBase
34+
}
35+
36+
throw "Pester 3.4.3 was not found in the repository packages folder or installed modules."
37+
}
38+
39+
function Import-PatchedPester {
40+
param(
41+
[Parameter(Mandatory = $true)]
42+
[string] $PesterModulePath
43+
)
44+
45+
$patchedPesterPath = Join-Path ([System.IO.Path]::GetTempPath()) ("Pester.3.4.3-pwsh-compatible-{0}" -f ([guid]::NewGuid().ToString("N")))
46+
47+
Copy-Item -Path $PesterModulePath -Destination $patchedPesterPath -Recurse -Force
48+
49+
$setupTeardownPath = Join-Path $patchedPesterPath "Functions" "SetupTeardown.ps1"
50+
$setupTeardown = [System.IO.File]::ReadAllText($setupTeardownPath)
51+
52+
$addTypePattern = '& \$SafeCommands\[''Add-Type''\] -TypeDefinition @''[\s\S]*?''@\r?\n\r?\n'
53+
$setupTeardown = [System.Text.RegularExpressions.Regex]::Replace($setupTeardown, $addTypePattern, "", 1)
54+
55+
$setupTeardown = $setupTeardown.Replace(
56+
'$closeIndex = [Pester.ClosingBraceFinder]::GetClosingBraceIndex($Tokens, $GroupStartTokenIndex)',
57+
@'
58+
$groupLevel = 1
59+
$closeIndex = -1
60+
61+
for ($i = $GroupStartTokenIndex + 1; $i -lt $Tokens.Length; $i++)
62+
{
63+
$type = $Tokens[$i].Type
64+
65+
if ($type -eq [System.Management.Automation.PSTokenType]::GroupStart)
66+
{
67+
$groupLevel++
68+
}
69+
elseif ($type -eq [System.Management.Automation.PSTokenType]::GroupEnd)
70+
{
71+
$groupLevel--
72+
73+
if ($groupLevel -le 0)
74+
{
75+
$closeIndex = $i
76+
break
77+
}
78+
}
79+
}
80+
'@)
81+
82+
[System.IO.File]::WriteAllText($setupTeardownPath, $setupTeardown)
83+
84+
Remove-Module Pester -ErrorAction SilentlyContinue
85+
Import-Module -Name (Join-Path $patchedPesterPath "Pester.psd1") -Force -ErrorAction Stop
86+
}
87+
88+
function Import-Pester {
89+
$pesterModulePath = Get-PesterModulePath
90+
91+
try {
92+
Import-Module -Name $pesterModulePath -RequiredVersion 3.4.3 -ErrorAction Stop
93+
} catch {
94+
if ($PSVersionTable.PSEdition -eq "Core" -and -not $IsWindows) {
95+
Write-Host "Importing a patched temporary copy of Pester 3.4.3 for pwsh compatibility."
96+
Import-PatchedPester -PesterModulePath $pesterModulePath
97+
} else {
98+
throw
99+
}
100+
}
101+
}
102+
103+
function Get-TestFiles {
104+
$discoveredFiles = Get-ChildItem -Path $testRootPath -Filter "*.tests.ps1" -Recurse
105+
if ([string]::IsNullOrWhiteSpace($Filter) -or $Filter -eq "*") {
106+
return @($discoveredFiles)
107+
}
108+
109+
return @(
110+
$discoveredFiles | Where-Object {
111+
$_.Name -like $Filter -or $_.FullName -like $Filter
112+
}
113+
)
114+
}
115+
116+
function Invoke-SelectedTests {
117+
param(
118+
[Parameter(Mandatory = $true)]
119+
[System.IO.FileInfo[]] $TestFiles
120+
)
121+
122+
foreach ($testFile in $TestFiles) {
123+
Write-Host "Running tests in: $($testFile.FullName)"
124+
if ($UsePassThruFailureCheck) {
125+
$result = Invoke-Pester -Path $testFile.FullName -PassThru
126+
if ($result.FailedCount -gt 0) {
127+
throw "Tests failed in $($testFile.FullName)."
128+
}
129+
} else {
130+
Invoke-Pester -Path $testFile.FullName
131+
}
132+
}
133+
}
134+
135+
try {
136+
if (-not $env:SystemRoot) {
137+
$env:SystemRoot = "C:\Windows"
138+
}
139+
if (-not $env:TEMP) {
140+
$env:TEMP = [System.IO.Path]::GetTempPath()
141+
}
142+
143+
foreach ($modulePath in $ImportModules) {
144+
Import-Module -Name $modulePath -ErrorAction Stop
145+
}
146+
147+
Import-Pester
148+
149+
if ($BeforeRun) {
150+
& $BeforeRun
151+
}
152+
153+
$testFiles = @(Get-TestFiles)
154+
if ($testFiles.Count -eq 0) {
155+
Write-Host "No matching test files found under $testRootPath for filter '$Filter'."
156+
return
157+
}
158+
159+
Invoke-SelectedTests -TestFiles $testFiles
160+
} finally {
161+
$env:SystemRoot = $originalSystemRoot
162+
$env:TEMP = $originalTemp
163+
}

tools/StepTemplatePacker/tests/ConvertTo-OctopusJson.Tests.ps1

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
$ErrorActionPreference = "Stop";
22
Set-StrictMode -Version "Latest";
33

4+
function Normalize-NewLines([string] $value) {
5+
if ($null -eq $value) {
6+
return $null;
7+
}
8+
9+
return $value -replace "`r`n", "`n";
10+
}
11+
412
Describe "ConvertTo-OctopusDeploy" {
513

614
It "InputObject is null" {
@@ -55,8 +63,8 @@ Describe "ConvertTo-OctopusDeploy" {
5563
It "InputObject is a populated array" {
5664
$input = @( $null, 100, "my string" );
5765
$expected = "[`r`n null,`r`n 100,`r`n `"my string`"`r`n]";
58-
ConvertTo-OctopusJson -InputObject $input `
59-
| Should Be $expected;
66+
Normalize-NewLines (ConvertTo-OctopusJson -InputObject $input) `
67+
| Should Be (Normalize-NewLines $expected);
6068
}
6169

6270
It "InputObject is an empty PSCustomObject" {
@@ -92,13 +100,14 @@ Describe "ConvertTo-OctopusDeploy" {
92100
}
93101
}
94102
"@
95-
ConvertTo-OctopusJson -InputObject $input `
96-
| Should Be $expected;
103+
$expected = $expected.Trim()
104+
Normalize-NewLines (ConvertTo-OctopusJson -InputObject $input) `
105+
| Should Be (Normalize-NewLines $expected);
97106
}
98107

99108
It "InputObject is an unhandled type" {
100109
{ ConvertTo-OctopusJson -InputObject ([System.Guid]::NewGuid()) } `
101110
| Should Throw "Unhandled input object type 'System.Guid'.";
102111
}
103112

104-
}
113+
}
Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1+
param(
2+
[string] $Filter = "*"
3+
)
4+
15
$ErrorActionPreference = "Stop";
26
Set-StrictMode -Version "Latest";
37

48
$thisScript = $MyInvocation.MyCommand.Path;
59
$thisFolder = [System.IO.Path]::GetDirectoryName($thisScript);
6-
7-
$packagesFolder = $thisFolder;
8-
$packagesFolder = [System.IO.Path]::GetDirectoryName($packagesFolder);
9-
$packagesFolder = [System.IO.Path]::GetDirectoryName($packagesFolder);
10-
$packagesFolder = [System.IO.Path]::GetDirectoryName($packagesFolder);
11-
$packagesFolder = [System.IO.Path]::Combine($packagesFolder, "packages");
12-
10+
$repoRoot = [System.IO.Path]::GetFullPath((Join-Path $thisFolder ".." ".." ".."));
1311
$packer = [System.IO.Path]::GetDirectoryName($thisFolder);
12+
$sharedRunner = Join-Path $repoRoot "tools" "Invoke-SharedPesterTests.ps1";
1413

15-
Import-Module -Name $packer;
16-
Import-Module -Name ([System.IO.Path]::Combine($packagesFolder, "Pester.3.4.3\tools\Pester"));
17-
18-
Invoke-Pester;
14+
& $sharedRunner `
15+
-TestRoot $thisFolder `
16+
-Filter $Filter `
17+
-ImportModules @($packer);

0 commit comments

Comments
 (0)