pester / Pester

Pester is the ubiquitous test and mock framework for PowerShell.
https://pester.dev/
Other
3.11k stars 473 forks source link

Custom assertion operators can't easily be reused #891

Closed brantb closed 7 years ago

brantb commented 7 years ago

I have a few custom assertion operators which I'd like to use in multiple test suites, but Pester only allows an assertion to be defined once.

Assertions.ps1

function IsAwesome($ActualValue, $ExpectedValue, [switch]$Negate) {
  # ... snip implementation ...
}
Add-AssertionOperator -Name IsAwesome -Test $function:IsAwesome

Get-SomethingInteresting.Tests.ps1

. "$PSScriptRoot\Assertions.ps1"
Describe 'Get-SomethingInteresting' {
  # ... snip tests ...
}

Set-SomethingInteresting.Tests.ps1

. "$PSScriptRoot\Assertions.ps1"
Describe 'Set-SomethingInteresting' {
  # ... snip ...
}

Actual result

PS> Invoke-Pester
Executing script Get-SomethingInteresting.Tests.ps1
  (...snip output...)
Executing script Set-SomethingInteresting.Tests.ps1
  [-] Error occurred in test script 'Set-SomethingInteresting.Tests.ps1' 59ms
    at Assert-AssertionOperatorNameIsUnique, C:\path\to\Pester\4.0.8\Pester.psm1: line 243
    Assertion operator name 'IsAwesome' has been added multiple times.

Expected result

I can reuse Assertions.ps1 in multiple test files, somehow.

As a workaround for this I could create a single TestEntryPoint.Tests.ps1 which dot-sources Assertions.ps1 plus all of my test files, then run my tests by calling Invoke-Pester -Script TestEntryPoint.Tests.ps1, but I like simply running Invoke-Pester and having everything work.

nohwnd commented 7 years ago

Yikes. There are few ways to solve this. One that seems most reasonable is relaxing the rule and simply do nothing when you add the same operator the second time. This should probably be optional so I think it would be reasonable to force the registration to provide a unique Id of the operator (think Guid, or better - hash of the file), when it registers multiple times. That should both:

The behavior would then be this:

You still would have a race condition when there would be two operators with the same name, id but different behavior, but those should be rare, and totally fault of the developer.

So now I wonder, how difficult would it be for us to hash the incoming scriptblock to do this Id stuff automatically :) Or you know we could just compare the script block strings :D So I guess that would be the solution:

seems fool proof enough.

brantb commented 7 years ago

Whoops, I didn't expect my force-pushes to clutter the issue history like that. My bad.