Skip to content

Instantly share code, notes, and snippets.

@ritalin
Last active January 30, 2019 08:22
Show Gist options
  • Save ritalin/88e8cabd0fd84724760918870f49a46a to your computer and use it in GitHub Desktop.
Save ritalin/88e8cabd0fd84724760918870f49a46a to your computer and use it in GitHub Desktop.
Pester operator for object properties matching.
Import-Module Pester -MinimumVersion 4.0.5 -Force -Scope Local
Import-Module (Get-Module Pester | % NestedModules | ? Name -eq "Format" | % Path) -Scope Local
function BeSame([object[]]$ActualValue, [object[]]$ExpectedValue, [switch]$Negate, [string[]]$Property = $null, [switch]$Loose) {
_AssertSameObject $ActualValue $ExpectedValue $Property $Negate $Loose $false
}
function BeSameExactly([object[]]$ActualValue, [object[]]$ExpectedValue, [switch]$Negate, [string[]]$Property = $null, [switch]$Loose) {
_AssertSameObject $ActualValue $ExpectedValue $Property $Negate $Loose $true
}
function _AssertSameObject([object[]]$ActualValues, [object[]]$ExpectedValues, [string[]]$Property, [bool]$Negate, [bool]$Loose, [bool]$StrictType) {
if ($ExpectedValues.Length -eq 0) {
return _MakeFalure "Expected value(s) is not specified."
}
if ($ActualValues.Length -ne $ExpectedValues.Length) {
return _MakeFalure "Element Count is not matched (actuals:$($ActualValues.Length) != epects:$($ExpectedValues.Length)"
}
if ($Property -eq $null) {
$Property = $ExpectedValues[0] | Get-Member -MemberType Properties | % Name
}
for ($i = 0; $i -lt $ActualValues.Length; ++$i) {
$a = $ActualValues[$i]
$e = $ExpectedValues[$i]
if ($StrictType) {
$actualType = $a.GetType()
$expectType = $e.GetType()
if ($actualType -ne $expectType) {
return _MakeFalure "At $($i)-th element, type is mismatched. (Expect: $actualType, but Actual: $expectType)"
}
}
$actualProps = $a | Get-Member -MemberType Properties | % Name
if (-not $Loose) {
[string[]]$unmatched = $Property | ?{ $_ -notin $actualProps }
if ($unmatched.Length -gt 0) {
return _MakeFalure "At $($i)-th element, property is not found $($unmatched -join ",")"
}
}
$falureProps = @()
foreach ($p in $Property) {
if ($p -in $actualProps) {
if ($Negate) {
if ($a."$p" -eq $e."$p") { $falureProps += $p }
}
else {
if ($a."$p" -ne $e."$p") { $falureProps += $p }
}
}
}
$success =
if ($Negate) {
$falureProps.Count -ne $Property.Length
}
else {
$falureProps.Count -eq 0
}
if (-not $success) {
$expectSubset = _SubsetValues $e $falureProps
$actualSubset = _SubsetValues $a $falureProps
$m = if ($Negate) { "matched property is found" } else { "property is not matched" }
return _MakeFalure "At $($i)-th element, $m. (Expected: $(Format-Nicely $expectSubset), Actual: $(Format-Nicely $actualSubset))"
}
}
[PSCustomObject]@{
Succeeded = $true; FailureMessage = ''
}
}
function _MakeFalure([string]$Message) {
[PSCustomObject]@{
Succeeded = $false
FailureMessage = $Message
}
}
function _SubsetValues([object]$v, [string[]]$props) {
foreach ($p in $props) { $v."$p" }
}
Add-AssertionOperator -Name BeSame -Test $function:BeSame -SupportsArrayInput
Add-AssertionOperator -Name BeSameExactly -Test $function:BeSameExactly -SupportsArrayInput
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment