Skip to content

Instantly share code, notes, and snippets.

@sean-m
Last active April 14, 2021 17:21
Show Gist options
  • Save sean-m/fe79fceb337946f56627def4551cd1b6 to your computer and use it in GitHub Desktop.
Save sean-m/fe79fceb337946f56627def4551cd1b6 to your computer and use it in GitHub Desktop.
Don't use this! Use Pester. Simple functions for writing assertion tests that will throw exceptions in a composable way without any external dependencies. All test functions return $true if passed so they can be used as a predicate, they throw on failure to stop script execution. This exists to simplify testing for invariants in production scrip…
class AssertionException : System.Exception {
AssertionException ([string]$Message, [System.Exception]$InnerException) : base($Message,$InnerException) { }
}
function Assert-Contains {
param (
[object[]]$Collection,
[string]$Property=$null,
$Pattern,
[Parameter(Mandatory=$true)]
[string]$ErrorMsg
)
if ($Property) {
if (-not ($Collection.$Property -like $Pattern)) {
throw New-Object System.Exception ($ErrorMsg)
}
}
else {
if (-not ($Collection -like $Pattern)) {
throw New-Object System.Exception ($ErrorMsg)
}
}
$true
}
function Assert-Comparison {
param (
[object[]]$Collection,
[string]$Property=$null,
[ValidateSet('lt','le','eq','ge','gt')]
$Operator,
$Value,
[Parameter(Mandatory=$true)]
[string]$ErrorMsg
)
$result = $false
foreach ($item in $Collection) {
$lvalue = $item
if ($Property) {
$lvalue = $item.$Property
}
switch ($Operator) {
'lt' { $result = $lvalue -lt $Value }
'le' { $result = $lvalue -le $Value }
'eq' { $result = $lvalue -eq $Value }
'ge' { $result = $lvalue -ge $Value }
'gt' { $result = $lvalue -gt $Value }
}
if ($result) { break }
}
if (-not $result) {
throw New-Object System.Exception ($ErrorMsg)
}
return $true
}
function Assert-Exists {
param (
$FilePath,
[ValidateSet("Any","Container","Leaf","Folder","File")]
$Type="Any"
)
$_type = $null
switch ($Type) {
'File' {
$_type = 'Leaf'
}
'Folder' {
$_type = 'Container'
}
default {
$_type = $Type
}
}
if (-not (Test-Path -Path $FilePath -PathType $_type)) {
throw New-Object System.Exception ("Path does not exist: '$FilePath' with type: $Type")
}
$true
}
function Assert-All {
# Of dubious utility
# Could just call assertions in-line
param (
[object[]]$Assertions
)
$count=1
try {
foreach ($a in $Assertions) {
& $a | Out-Null
$count++
}
}
catch {
$assertion_string = $Assertions[$count-1].ToString()
$ex = [AssertionException]::new("Assertion $count failed! : $assertion_string", $_.Exception)
throw $ex
}
$true
}
function Get-ExceptionMessages {
param (
[Exception]$Exception,
[string]$Message="",
[int]$Level=1
)
if ($Exception.Message) {
if ($Message) {
$Message += "`n$Level :`t$($Exception.Message)"
}
else {
$Message = "Exception messages, outer to inner:`n$Level :`t$($Exception.Message)"
}
}
$result=$null
if ($Exception.InnerException) {
$result = Get-ExceptionMessages -Exception $Exception.InnerException -Message $Message -Level ($Level+1)
}
else {
$result = $Message
}
return $result
}
## Test for the existence of files or anything with a PSProvider: registry, ActiveDirectory, etc.
Assert-Exists -FilePath C:\Intel
Assert-Exists -FilePath C:\Intel -Type File
Assert-Exists -FilePath C:\Intel -Type Folder
## Test that a comparison is true for at least one item in a collection
# Works with testing DateTime values
Assert-Comparison -Collection @([DateTime]::MaxValue, (Get-Date)) -Operator lt -Value (Get-Date) -ErrorMsg "Nothing in the past"
# Can compare property values
$files = Get-ChildItem .
Assert-Comparison -Collection $files -Property 'LastWriteTime' -Operator ge -Value ((Get-Date).AddDays(-1)) -ErrorMsg "Does not contain recent files."
## Test that at a simple pattern matches at least one item in a collection
# Works with values or properties
class Person {
$Name
$Age
}
$1 = New-Object Person -Property @{ Name="Patrick"; Age=10 }
$2 = New-Object Person -Property @{ Name="Alex"; Age=8 }
$3 = New-Object Person -Property @{ Name="Nicole"; Age=6 }
Assert-Contains -Collection @('Apple','Orange','Banana','Corn') -Pattern "*orn" -ErrorMsg "Whoops"
Assert-Contains -Collection @($1, $2, $3) -Property 'Name' -Pattern "Nic*" -ErrorMsg "Whoops"
Assert-Contains -Collection @($1, $2, $3) -Property 'Age' -Pattern 6 -ErrorMsg "Whoops"
## Verify that a collection of assertions are true and throw once if they arent.
try {
Assert-All -Assertions @(
{ Assert-Exists -FilePath C:\Intel },
{ Assert-Contains -Collection @('Apple','Orange','Banana','Corn') -Pattern "*orn" -ErrorMsg "Whoops" },
{ Assert-Contains -Collection @('Apple','Orange','Banana') -Pattern "*orn" -ErrorMsg "Whoops" },
{ Assert-Contains -Collection @($1, $2, $3) -Property 'Name' -Pattern "Pat*" -ErrorMsg "Whoops" }
)
}
catch {
# Recurse into inner exceptions and stack messages for convenience with logging.
Get-ExceptionMessages -Exception $_.Exception
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment