Skip to content

Instantly share code, notes, and snippets.

@davidlu1001
Created July 4, 2024 07:07
Show Gist options
  • Save davidlu1001/9081a503f8c16e838d108e0be669f31f to your computer and use it in GitHub Desktop.
Save davidlu1001/9081a503f8c16e838d108e0be669f31f to your computer and use it in GitHub Desktop.
Testing RemoteOps.ps1 with Pester
# RemoteOps.Tests.ps1
BeforeAll {
. $PSScriptRoot\RemoteOps.ps1
Mock Write-Log {}
Mock Resolve-FullPath { $Path }
Mock Get-Content { "Write-Output 'Test Script'" }
}
Describe "RemoteOps - Command Execution" {
BeforeEach {
Mock Invoke-Command {
[PSCustomObject]@{
PSComputerName = $ComputerName
Status = "Success"
Output = "Command executed successfully"
}
}
}
It "Executes a command on a single remote host" {
$result = .\RemoteOps.ps1 -ComputerName "Server1" -Command "Get-Process"
$result.ComputerName | Should -Be "Server1"
$result.Status | Should -Be "Success"
}
It "Executes a command on multiple remote hosts" {
$result = .\RemoteOps.ps1 -ComputerName "Server1","Server2" -Command "Get-Service"
$result.Count | Should -Be 2
$result[0].ComputerName | Should -Be "Server1"
$result[1].ComputerName | Should -Be "Server2"
}
It "Handles command execution timeout" {
Mock Invoke-Command { Start-Sleep -Seconds 10 }
{ .\RemoteOps.ps1 -ComputerName "SlowServer" -Command "Get-Process" -Timeout 5 } | Should -Throw "Operation timed out after 5 seconds"
}
It "Respects ThrottleLimit parameter" {
$result = .\RemoteOps.ps1 -ComputerName "Server1","Server2","Server3" -Command "Get-Process" -ThrottleLimit 2
$result.Count | Should -Be 3
Should -Invoke Invoke-Command -Times 1 -ParameterFilter { $ThrottleLimit -eq 2 }
}
}
Describe "RemoteOps - Script Execution" {
BeforeEach {
Mock Invoke-Command {
[PSCustomObject]@{
PSComputerName = $ComputerName
Status = "Success"
Output = "Script executed successfully"
}
}
Mock Test-Path { $true }
}
It "Executes a script on a remote host" {
$result = .\RemoteOps.ps1 -ComputerName "Server1" -ScriptPath "C:\Scripts\Test.ps1"
$result.ComputerName | Should -Be "Server1"
$result.Status | Should -Be "Success"
}
It "Executes a script with arguments" {
$result = .\RemoteOps.ps1 -ComputerName "Server1" -ScriptPath "C:\Scripts\Test.ps1" -ArgumentList @{Param1 = "Value1"; Param2 = "Value2"}
$result.ComputerName | Should -Be "Server1"
$result.Status | Should -Be "Success"
Should -Invoke Invoke-Command -Times 1 -ParameterFilter { $ArgumentList[0].ArgumentList.Param1 -eq "Value1" }
}
It "Handles non-existent script file" {
Mock Test-Path { $false }
{ .\RemoteOps.ps1 -ComputerName "Server1" -ScriptPath "C:\NonExistent.ps1" } | Should -Throw "Script file not found"
}
It "Handles relative script paths" {
$result = .\RemoteOps.ps1 -ComputerName "Server1" -ScriptPath ".\Test.ps1"
$result.Status | Should -Be "Success"
Should -Invoke Resolve-FullPath -Times 1 -ParameterFilter { $Path -eq ".\Test.ps1" }
}
}
Describe "RemoteOps - Copy Operations" {
BeforeEach {
Mock Invoke-Command {
[PSCustomObject]@{
PSComputerName = $ComputerName
Status = "Success"
Output = "File/Directory copied successfully"
}
}
Mock Test-Path { $true }
}
It "Copies a single file to a remote host" {
$result = .\RemoteOps.ps1 -ComputerName "Server1" -Source "C:\LocalFile.txt" -Destination "C:\RemoteFolder"
$result.ComputerName | Should -Be "Server1"
$result.Status | Should -Be "Success"
}
It "Copies multiple files to a remote host" {
$result = .\RemoteOps.ps1 -ComputerName "Server1" -Source "C:\File1.txt","C:\File2.txt" -Destination "C:\RemoteFolder"
$result.ComputerName | Should -Be "Server1"
$result.Status | Should -Be "Success"
Should -Invoke Invoke-Command -Times 1 -ParameterFilter { $ArgumentList[0].Source.Count -eq 2 }
}
It "Copies a directory to a remote host" {
$result = .\RemoteOps.ps1 -ComputerName "Server1" -Source "C:\LocalFolder" -Destination "C:\RemoteFolder"
$result.ComputerName | Should -Be "Server1"
$result.Status | Should -Be "Success"
}
It "Handles non-existent source path" {
Mock Test-Path { $false }
{ .\RemoteOps.ps1 -ComputerName "Server1" -Source "C:\NonExistent" -Destination "C:\Remote" } | Should -Throw "Cannot find path"
}
It "Handles relative source paths" {
$result = .\RemoteOps.ps1 -ComputerName "Server1" -Source ".\LocalFile.txt" -Destination "C:\RemoteFolder"
$result.Status | Should -Be "Success"
Should -Invoke Resolve-FullPath -Times 1 -ParameterFilter { $Path -eq ".\LocalFile.txt" }
}
}
Describe "RemoteOps - Config File Handling" {
BeforeEach {
Mock Invoke-Command {
[PSCustomObject]@{
PSComputerName = $ComputerName
Status = "Success"
Output = "Operation completed"
}
}
Mock Test-Path { $true }
Mock Get-Content { @("Server1", "Server2", "Server3") }
}
It "Uses computers from config file" {
$result = .\RemoteOps.ps1 -ConfigFile "C:\servers.txt" -Command "Get-Process"
$result.Count | Should -Be 3
$result[0].ComputerName | Should -Be "Server1"
$result[1].ComputerName | Should -Be "Server2"
$result[2].ComputerName | Should -Be "Server3"
}
It "Handles non-existent config file" {
Mock Test-Path { $false }
{ .\RemoteOps.ps1 -ConfigFile "C:\NonExistent.txt" -Command "Get-Process" } | Should -Throw "Config file not found"
}
It "Handles empty config file" {
Mock Get-Content { @() }
{ .\RemoteOps.ps1 -ConfigFile "C:\EmptyConfig.txt" -Command "Get-Process" } | Should -Throw "No valid hosts found in config file"
}
It "Handles relative config file path" {
$result = .\RemoteOps.ps1 -ConfigFile ".\servers.txt" -Command "Get-Process"
$result.Count | Should -Be 3
Should -Invoke Resolve-FullPath -Times 1 -ParameterFilter { $Path -eq ".\servers.txt" }
}
}
Describe "RemoteOps - Error Handling and Edge Cases" {
BeforeEach {
Mock Invoke-Command { throw "Remote execution failed" }
}
It "Handles remote execution errors" {
$result = .\RemoteOps.ps1 -ComputerName "FailServer" -Command "Get-Process"
$result.Status | Should -Be "Error"
$result.Output | Should -BeLike "*Remote execution failed*"
}
It "Handles invalid parameter combinations" {
{ .\RemoteOps.ps1 -ComputerName "Server1" } | Should -Throw "Parameter set cannot be resolved"
}
It "Handles invalid ThrottleLimit" {
{ .\RemoteOps.ps1 -ComputerName "Server1" -Command "Get-Process" -ThrottleLimit 0 } | Should -Throw "Cannot validate argument on parameter 'ThrottleLimit'"
}
It "Handles invalid Timeout" {
{ .\RemoteOps.ps1 -ComputerName "Server1" -Command "Get-Process" -Timeout 0 } | Should -Throw "Cannot validate argument on parameter 'Timeout'"
}
It "Handles missing ComputerName and ConfigFile" {
{ .\RemoteOps.ps1 -Command "Get-Process" } | Should -Throw "No remote hosts specified"
}
}
Describe "RemoteOps - DryRun Functionality" {
It "Displays expected operations without executing them" {
$output = .\RemoteOps.ps1 -ComputerName "Server1" -Command "Get-Process" -DryRun
$output | Should -BeLike "*would execute command: Get-Process*"
}
It "Displays copy operations in dry run mode" {
$output = .\RemoteOps.ps1 -ComputerName "Server1" -Source "C:\LocalFile.txt" -Destination "C:\RemoteFolder" -DryRun
$output | Should -BeLike "*Would copy files/directories from C:\LocalFile.txt to C:\RemoteFolder on Server1*"
}
}
Describe "RemoteOps - Output File Handling" {
BeforeEach {
Mock Invoke-Command {
[PSCustomObject]@{
PSComputerName = $ComputerName
Status = "Success"
Output = "Operation completed"
}
}
Mock Export-Csv {}
}
It "Exports results to CSV file" {
$result = .\RemoteOps.ps1 -ComputerName "Server1" -Command "Get-Process" -OutputFile "results.csv"
Should -Invoke Export-Csv -Times 1 -ParameterFilter { $Path -eq "results.csv" }
}
It "Handles relative output file path" {
$result = .\RemoteOps.ps1 -ComputerName "Server1" -Command "Get-Process" -OutputFile ".\results.csv"
Should -Invoke Resolve-FullPath -Times 1 -ParameterFilter { $Path -eq ".\results.csv" }
}
}
Describe "RemoteOps - Parallel Execution" {
It "Executes operations in parallel" {
Mock Invoke-Command {
Start-Sleep -Milliseconds 100
[PSCustomObject]@{
PSComputerName = $ComputerName
Status = "Success"
Output = "Operation completed"
}
}
$start = Get-Date
$result = .\RemoteOps.ps1 -ComputerName "Server1","Server2","Server3" -Command "Get-Process" -ThrottleLimit 3
$end = Get-Date
$duration = ($end - $start).TotalMilliseconds
$duration | Should -BeLessThan 300
$result.Count | Should -Be 3
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment