mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-08-30 16:59:47 +00:00
refactor: make all integration test files self-contained
Each test file now creates and cleans up its own resources: - 06_VMs: restores own AfterAll cleanup for pester-test-vm - 07_Snapshots: creates pester-snap-vm, tests snapshots, cleans up - 09_CloudInit: creates pester-ci-vm with cloud-init drive, cleans up - 15_Tasks: creates pester-task-vm, tests task CRUD, cleans up Removed cross-file dependency helpers (Find-TestVm, Register-TestResource) from _IntegrationHelper.ps1 — no longer needed. Each file can now run independently via -Tests filter. If a Setup context fails, subsequent tests in the same file skip gracefully. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,8 +17,17 @@ BeforeAll {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AfterAll {
|
AfterAll {
|
||||||
# Do NOT clean up pester-test-vm here — later test files (07_Snapshots,
|
if (-not $script:SkipReason -and $script:TestVmId) {
|
||||||
# 09_CloudInit, 15_Tasks) depend on it. 99_Cleanup handles removal.
|
foreach ($vmId in @($script:TestVmId, ($script:TestVmId + 1000))) {
|
||||||
|
try {
|
||||||
|
Stop-PveVm -Node $script:Node -VmId $vmId -Wait -Timeout 30 -Confirm:$false -ErrorAction SilentlyContinue | Out-Null
|
||||||
|
} catch { }
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
try {
|
||||||
|
Remove-PveVm -Node $script:Node -VmId $vmId -Force -Purge -Confirm:$false -ErrorAction SilentlyContinue
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
Disconnect-TestPve
|
Disconnect-TestPve
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +58,6 @@ Describe 'VMs — Integration' -Tag 'Integration' {
|
|||||||
$vm | Should -Not -BeNullOrEmpty
|
$vm | Should -Not -BeNullOrEmpty
|
||||||
|
|
||||||
$script:TestVmId = $vm.VmId
|
$script:TestVmId = $vm.VmId
|
||||||
Register-TestResource -Name 'pester-test-vm' -VmId $vm.VmId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'Should get and set VM config' {
|
It 'Should get and set VM config' {
|
||||||
|
|||||||
@@ -4,13 +4,12 @@ BeforeAll {
|
|||||||
. $PSScriptRoot/_IntegrationHelper.ps1
|
. $PSScriptRoot/_IntegrationHelper.ps1
|
||||||
Connect-TestPve
|
Connect-TestPve
|
||||||
|
|
||||||
# Find the test VM created by 06_VMs.Tests.ps1
|
$script:SnapVmId = $null
|
||||||
$script:TestVmId = Find-TestVm
|
|
||||||
|
|
||||||
function script:Skip-IfNoTestVm {
|
function script:Skip-IfNoSnapVm {
|
||||||
if (Skip-IfNoTarget) { return $true }
|
if (Skip-IfNoTarget) { return $true }
|
||||||
if ($null -eq $script:TestVmId) {
|
if ($null -eq $script:SnapVmId) {
|
||||||
Set-ItResult -Skipped -Because 'No test VM found (pester-test-vm must exist from 06_VMs)'
|
Set-ItResult -Skipped -Because 'Snapshot test VM was not created'
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
return $false
|
return $false
|
||||||
@@ -18,28 +17,49 @@ BeforeAll {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AfterAll {
|
AfterAll {
|
||||||
# Snapshot cleanup is inline (remove within the test).
|
if (-not $script:SkipReason -and $script:SnapVmId) {
|
||||||
# No VM cleanup here — 06_VMs owns pester-test-vm.
|
try {
|
||||||
|
Stop-PveVm -Node $script:Node -VmId $script:SnapVmId -Wait -Timeout 30 -Confirm:$false -ErrorAction SilentlyContinue | Out-Null
|
||||||
|
} catch { }
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
try {
|
||||||
|
Remove-PveVm -Node $script:Node -VmId $script:SnapVmId -Force -Purge -Confirm:$false -ErrorAction SilentlyContinue
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
Disconnect-TestPve
|
Disconnect-TestPve
|
||||||
}
|
}
|
||||||
|
|
||||||
Describe 'Snapshots — Integration' -Tag 'Integration' {
|
Describe 'Snapshots — Integration' -Tag 'Integration' {
|
||||||
|
Context 'Setup' {
|
||||||
|
It 'Should create a VM for snapshot tests' {
|
||||||
|
if (Skip-IfNoTarget) { return }
|
||||||
|
|
||||||
|
$task = New-PveVm `
|
||||||
|
-Node $script:Node `
|
||||||
|
-Name 'pester-snap-vm' `
|
||||||
|
-Memory 128 `
|
||||||
|
-Cores 1 `
|
||||||
|
-Wait
|
||||||
|
|
||||||
|
$task | Should -Not -BeNullOrEmpty
|
||||||
|
|
||||||
|
$vm = Get-PveVm -Node $script:Node -Name 'pester-snap-vm' |
|
||||||
|
Select-Object -First 1
|
||||||
|
$vm | Should -Not -BeNullOrEmpty
|
||||||
|
$script:SnapVmId = $vm.VmId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Context 'Snapshots' {
|
Context 'Snapshots' {
|
||||||
It 'Should create, list, and remove a snapshot' {
|
It 'Should create, list, and remove a snapshot' {
|
||||||
if (Skip-IfNoTestVm) { return }
|
if (Skip-IfNoSnapVm) { return }
|
||||||
|
|
||||||
# Ensure the VM is stopped for snapshot
|
|
||||||
$vm = Get-PveVm -Node $script:Node | Where-Object { $_.VmId -eq $script:TestVmId }
|
|
||||||
if ($vm.Status -eq 'running') {
|
|
||||||
Stop-PveVm -Node $script:Node -VmId $script:TestVmId -Wait -Timeout 30 -Confirm:$false | Out-Null
|
|
||||||
}
|
|
||||||
|
|
||||||
$snapName = 'pester-snap'
|
$snapName = 'pester-snap'
|
||||||
|
|
||||||
# Create
|
# Create
|
||||||
$createTask = New-PveSnapshot `
|
$createTask = New-PveSnapshot `
|
||||||
-Node $script:Node `
|
-Node $script:Node `
|
||||||
-VmId $script:TestVmId `
|
-VmId $script:SnapVmId `
|
||||||
-Name $snapName `
|
-Name $snapName `
|
||||||
-Description 'Created by Pester integration test' `
|
-Description 'Created by Pester integration test' `
|
||||||
-Wait
|
-Wait
|
||||||
@@ -47,14 +67,14 @@ Describe 'Snapshots — Integration' -Tag 'Integration' {
|
|||||||
$createTask | Should -Not -BeNullOrEmpty
|
$createTask | Should -Not -BeNullOrEmpty
|
||||||
|
|
||||||
# List and verify
|
# List and verify
|
||||||
$snapshots = Get-PveSnapshot -Node $script:Node -VmId $script:TestVmId
|
$snapshots = Get-PveSnapshot -Node $script:Node -VmId $script:SnapVmId
|
||||||
$snap = $snapshots | Where-Object { $_.Name -eq $snapName }
|
$snap = $snapshots | Where-Object { $_.Name -eq $snapName }
|
||||||
$snap | Should -Not -BeNullOrEmpty
|
$snap | Should -Not -BeNullOrEmpty
|
||||||
|
|
||||||
# Restore
|
# Restore
|
||||||
{ Restore-PveSnapshot `
|
{ Restore-PveSnapshot `
|
||||||
-Node $script:Node `
|
-Node $script:Node `
|
||||||
-VmId $script:TestVmId `
|
-VmId $script:SnapVmId `
|
||||||
-Name $snapName `
|
-Name $snapName `
|
||||||
-Confirm:$false `
|
-Confirm:$false `
|
||||||
-Wait } | Should -Not -Throw
|
-Wait } | Should -Not -Throw
|
||||||
@@ -62,7 +82,7 @@ Describe 'Snapshots — Integration' -Tag 'Integration' {
|
|||||||
# Remove
|
# Remove
|
||||||
$removeTask = Remove-PveSnapshot `
|
$removeTask = Remove-PveSnapshot `
|
||||||
-Node $script:Node `
|
-Node $script:Node `
|
||||||
-VmId $script:TestVmId `
|
-VmId $script:SnapVmId `
|
||||||
-Name $snapName `
|
-Name $snapName `
|
||||||
-Confirm:$false `
|
-Confirm:$false `
|
||||||
-Wait
|
-Wait
|
||||||
|
|||||||
@@ -4,39 +4,81 @@ BeforeAll {
|
|||||||
. $PSScriptRoot/_IntegrationHelper.ps1
|
. $PSScriptRoot/_IntegrationHelper.ps1
|
||||||
Connect-TestPve
|
Connect-TestPve
|
||||||
|
|
||||||
# Find a test VM for cloud-init config read test
|
$script:CiVmId = $null
|
||||||
$script:TestVmId = Find-TestVm
|
|
||||||
$script:LinuxVmId = Find-TestVm -Name 'pester-linux-vm'
|
function script:Skip-IfNoCiVm {
|
||||||
|
if (Skip-IfNoTarget) { return $true }
|
||||||
|
if ($null -eq $script:CiVmId) {
|
||||||
|
Set-ItResult -Skipped -Because 'Cloud-init test VM was not created'
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
return $false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AfterAll {
|
AfterAll {
|
||||||
# Read-only tests — no cleanup needed
|
if (-not $script:SkipReason -and $script:CiVmId) {
|
||||||
|
try {
|
||||||
|
Stop-PveVm -Node $script:Node -VmId $script:CiVmId -Wait -Timeout 30 -Confirm:$false -ErrorAction SilentlyContinue | Out-Null
|
||||||
|
} catch { }
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
try {
|
||||||
|
Remove-PveVm -Node $script:Node -VmId $script:CiVmId -Force -Purge -Confirm:$false -ErrorAction SilentlyContinue
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
Disconnect-TestPve
|
Disconnect-TestPve
|
||||||
}
|
}
|
||||||
|
|
||||||
Describe 'Cloud-Init — Integration' -Tag 'Integration' {
|
Describe 'Cloud-Init — Integration' -Tag 'Integration' {
|
||||||
|
|
||||||
|
Context 'Setup' {
|
||||||
|
It 'Should create a VM with cloud-init drive' {
|
||||||
|
if (Skip-IfNoTarget) { return }
|
||||||
|
|
||||||
|
$task = New-PveVm `
|
||||||
|
-Node $script:Node `
|
||||||
|
-Name 'pester-ci-vm' `
|
||||||
|
-Memory 128 `
|
||||||
|
-Cores 1 `
|
||||||
|
-Wait
|
||||||
|
|
||||||
|
$task | Should -Not -BeNullOrEmpty
|
||||||
|
|
||||||
|
$vm = Get-PveVm -Node $script:Node -Name 'pester-ci-vm' |
|
||||||
|
Select-Object -First 1
|
||||||
|
$vm | Should -Not -BeNullOrEmpty
|
||||||
|
$script:CiVmId = $vm.VmId
|
||||||
|
|
||||||
|
# Add a cloud-init drive
|
||||||
|
Set-PveVmConfig -Node $script:Node -VmId $script:CiVmId `
|
||||||
|
-AdditionalConfig @{ ide2 = "$($script:Storage):cloudinit" } `
|
||||||
|
-ErrorAction Stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Context 'Cloud-Init' {
|
Context 'Cloud-Init' {
|
||||||
It 'Should get cloud-init config' {
|
It 'Should get cloud-init config' {
|
||||||
if (Skip-IfNoTarget) { return }
|
if (Skip-IfNoCiVm) { return }
|
||||||
if ($null -eq $script:TestVmId) {
|
|
||||||
Set-ItResult -Skipped -Because 'No test VM found'
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get-PveCloudInitConfig should not throw even if the VM has no cloud-init drive.
|
{ Get-PveCloudInitConfig -Node $script:Node -VmId $script:CiVmId -ErrorAction Stop } |
|
||||||
{ Get-PveCloudInitConfig -Node $script:Node -VmId $script:TestVmId -ErrorAction Stop } |
|
|
||||||
Should -Not -Throw
|
Should -Not -Throw
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'Should regenerate cloud-init image (Invoke-PveCloudInitRegenerate)' {
|
It 'Should set cloud-init config' {
|
||||||
if (Skip-IfNoTarget) { return }
|
if (Skip-IfNoCiVm) { return }
|
||||||
if ($null -eq $script:LinuxVmId) {
|
|
||||||
Set-ItResult -Skipped -Because 'Linux VM was not provisioned (PVETEST_PASSWORD may not be set)'
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
# The Linux VM has a cloud-init drive from provisioning
|
{ Set-PveCloudInitConfig -Node $script:Node -VmId $script:CiVmId `
|
||||||
{ Invoke-PveCloudInitRegenerate -Node $script:Node -VmId $script:LinuxVmId -Wait -ErrorAction Stop } |
|
-CiUser 'pester-user' -ErrorAction Stop } |
|
||||||
|
Should -Not -Throw
|
||||||
|
|
||||||
|
$config = Get-PveCloudInitConfig -Node $script:Node -VmId $script:CiVmId -ErrorAction Stop
|
||||||
|
$config.CiUser | Should -Be 'pester-user'
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'Should regenerate cloud-init image' {
|
||||||
|
if (Skip-IfNoCiVm) { return }
|
||||||
|
|
||||||
|
{ Invoke-PveCloudInitRegenerate -Node $script:Node -VmId $script:CiVmId -Wait -ErrorAction Stop } |
|
||||||
Should -Not -Throw
|
Should -Not -Throw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ Describe 'Linux VM — Integration' -Tag 'Integration' {
|
|||||||
|
|
||||||
$script:LinuxVmId = $vm.VmId
|
$script:LinuxVmId = $vm.VmId
|
||||||
$script:CreatedVmIds.Add($vm.VmId)
|
$script:CreatedVmIds.Add($vm.VmId)
|
||||||
Register-TestResource -Name 'pester-linux-vm' -VmId $vm.VmId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'Should import cloud image disk (Import-PveVmDisk)' {
|
It 'Should import cloud image disk (Import-PveVmDisk)' {
|
||||||
|
|||||||
@@ -4,27 +4,59 @@ BeforeAll {
|
|||||||
. $PSScriptRoot/_IntegrationHelper.ps1
|
. $PSScriptRoot/_IntegrationHelper.ps1
|
||||||
Connect-TestPve
|
Connect-TestPve
|
||||||
|
|
||||||
# Find an existing test VM to use for task tests
|
$script:TaskVmId = $null
|
||||||
$script:TestVmId = Find-TestVm
|
|
||||||
|
function script:Skip-IfNoTaskVm {
|
||||||
|
if (Skip-IfNoTarget) { return $true }
|
||||||
|
if ($null -eq $script:TaskVmId) {
|
||||||
|
Set-ItResult -Skipped -Because 'Task test VM was not created'
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
return $false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AfterAll {
|
AfterAll {
|
||||||
# Read-only tests — no cleanup needed
|
if (-not $script:SkipReason -and $script:TaskVmId) {
|
||||||
|
try {
|
||||||
|
Stop-PveVm -Node $script:Node -VmId $script:TaskVmId -Wait -Timeout 30 -Confirm:$false -ErrorAction SilentlyContinue | Out-Null
|
||||||
|
} catch { }
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
try {
|
||||||
|
Remove-PveVm -Node $script:Node -VmId $script:TaskVmId -Force -Purge -Confirm:$false -ErrorAction SilentlyContinue
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
Disconnect-TestPve
|
Disconnect-TestPve
|
||||||
}
|
}
|
||||||
|
|
||||||
Describe 'Tasks — Integration' -Tag 'Integration' {
|
Describe 'Tasks — Integration' -Tag 'Integration' {
|
||||||
|
|
||||||
|
Context 'Setup' {
|
||||||
|
It 'Should create a VM for task tests' {
|
||||||
|
if (Skip-IfNoTarget) { return }
|
||||||
|
|
||||||
|
$task = New-PveVm `
|
||||||
|
-Node $script:Node `
|
||||||
|
-Name 'pester-task-vm' `
|
||||||
|
-Memory 128 `
|
||||||
|
-Cores 1 `
|
||||||
|
-Wait
|
||||||
|
|
||||||
|
$task | Should -Not -BeNullOrEmpty
|
||||||
|
|
||||||
|
$vm = Get-PveVm -Node $script:Node -Name 'pester-task-vm' |
|
||||||
|
Select-Object -First 1
|
||||||
|
$vm | Should -Not -BeNullOrEmpty
|
||||||
|
$script:TaskVmId = $vm.VmId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Context 'Tasks' {
|
Context 'Tasks' {
|
||||||
It 'Should get a task by UPID and wait for completion' {
|
It 'Should get a task by UPID and wait for completion' {
|
||||||
if (Skip-IfNoTarget) { return }
|
if (Skip-IfNoTaskVm) { return }
|
||||||
if ($null -eq $script:TestVmId) {
|
|
||||||
Set-ItResult -Skipped -Because 'No test VM was created'
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
# Start the VM to get a task object
|
# Start the VM to get a task object
|
||||||
$startResult = Start-PveVm -Node $script:Node -VmId $script:TestVmId
|
$startResult = Start-PveVm -Node $script:Node -VmId $script:TaskVmId
|
||||||
$startResult | Should -Not -BeNullOrEmpty
|
$startResult | Should -Not -BeNullOrEmpty
|
||||||
$startResult.Upid | Should -Not -BeNullOrEmpty
|
$startResult.Upid | Should -Not -BeNullOrEmpty
|
||||||
|
|
||||||
@@ -36,8 +68,12 @@ Describe 'Tasks — Integration' -Tag 'Integration' {
|
|||||||
$task | Should -Not -BeNullOrEmpty
|
$task | Should -Not -BeNullOrEmpty
|
||||||
$task.IsSuccessful | Should -BeTrue
|
$task.IsSuccessful | Should -BeTrue
|
||||||
|
|
||||||
# Clean up
|
# List tasks
|
||||||
Stop-PveVm -Node $script:Node -VmId $script:TestVmId -Wait -Timeout 30 -Confirm:$false | Out-Null
|
$tasks = Get-PveTaskList -Node $script:Node
|
||||||
|
$tasks | Should -Not -BeNullOrEmpty
|
||||||
|
|
||||||
|
# Clean up — stop the VM
|
||||||
|
Stop-PveVm -Node $script:Node -VmId $script:TaskVmId -Wait -Timeout 30 -Confirm:$false | Out-Null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,43 +145,3 @@ function script:Disconnect-TestPve {
|
|||||||
#>
|
#>
|
||||||
try { Disconnect-PveServer -ErrorAction SilentlyContinue } catch { }
|
try { Disconnect-PveServer -ErrorAction SilentlyContinue } catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Resource discovery helpers ───────────────────────────────────────────
|
|
||||||
# These allow later test files to find resources created by earlier files
|
|
||||||
# without sharing script-scoped variables. If the resource doesn't exist,
|
|
||||||
# the caller gets $null and should skip.
|
|
||||||
|
|
||||||
function script:Find-TestVm {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Finds the pester-test-vm by checking env state or querying PVE.
|
|
||||||
#>
|
|
||||||
param([string]$Name = 'pester-test-vm')
|
|
||||||
|
|
||||||
# Check env var first (set by the file that created it)
|
|
||||||
$envKey = "PVETEST_STATE_$($Name.Replace('-','_').ToUpper())"
|
|
||||||
$vmId = [System.Environment]::GetEnvironmentVariable($envKey)
|
|
||||||
if ($vmId) { return [int]$vmId }
|
|
||||||
|
|
||||||
# Fall back to querying PVE
|
|
||||||
try {
|
|
||||||
$vms = Get-PveVm -Node $script:Node -ErrorAction Stop
|
|
||||||
$match = $vms | Where-Object { $_.Name -eq $Name } | Select-Object -First 1
|
|
||||||
if ($match) { return [int]$match.VmId }
|
|
||||||
} catch { }
|
|
||||||
|
|
||||||
return $null
|
|
||||||
}
|
|
||||||
|
|
||||||
function script:Register-TestResource {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Registers a resource VMID in env for cross-file discovery.
|
|
||||||
#>
|
|
||||||
param(
|
|
||||||
[string]$Name,
|
|
||||||
[int]$VmId
|
|
||||||
)
|
|
||||||
$envKey = "PVETEST_STATE_$($Name.Replace('-','_').ToUpper())"
|
|
||||||
[System.Environment]::SetEnvironmentVariable($envKey, $VmId.ToString())
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user