pester / Pester

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

Suggest to add an option to assert the correct number of items in a collection to Pester v6 #2534

Open johlju opened 2 months ago

johlju commented 2 months ago

Checklist

Summary of the feature request

Currently the new assertions for Pester v6 does not support a way for just asserting the correct number of objects in a collection similar to v5's Should -HaveCount. To use command Should-BeCollection one must also provide the actual values in the collection for the assert ot work. Suggest to add a parameter SkipValueComparison or CountOnly to just assert the correct number of items.

How should it work?

Use a switch parameter and use the Expected positional parameter for the expected count number.

 1, 2, 3 | Should-BeCollection 3 -SkipValueComparison
# or
 1, 2, 3 | Should-BeCollection 3 -CountOnly

Use a named parameter to also pass the expected count number.

 1, 2, 3 | Should-BeCollection -SkipValueComparison 3
# or
 1, 2, 3 | Should-BeCollection -CountOnly 3

Or add a command Should-HaveCount. Example code:

function Should-HaveCount
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [ValidateNotNullOrEmpty()]
        [System.Object[]]
        $InputObject,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [int]
        $Expected
    )

    begin
    {
        $actualCount = 0
    }

    process
    {
        $InputObject.ForEach({$actualCount += 1})
    }

    end
    {
        if ($actualCount -ne $Expected)
        {
            Write-Information -MessageData "Expected $Expected items, but got $actualCount" -InformationAction 'Continue'
        }
        else 
        {
            Write-Information -MessageData "Got correct count!" -InformationAction 'Continue'
        }
    }
}

$someCollection = @('a', 'b', 'c')
Should-HaveCount -InputObject $someCollection -Expected 3
$someCollection | Should-HaveCount -Expected 3
$someCollection | Should-HaveCount -Expected 4
johlju commented 2 months ago

It might be another way we are expected to handle this in v6, I added this issue to discuss how the Should -HaveCount should be converted to the (future) Pester v6 syntax. 🙂

fflaten commented 2 months ago

My immediate suggestion would be to recommend using @().Count | Should -Be* 2 etc. going forward.

It's easy to use, works with Should-Be/BeGreaterThan*/BeLessThan* and we avoid issues with dictionary and typed objects (e.g. [System.Array]) not working because we struggle with special collections vs single-item arrays. Just include a bunch of examples in our migration docs to cover the common scenarios.

@nohwnd: Does the new Collect-Input approach make the collection vs single item array issue solvable?

nohwnd commented 2 months ago

I was thinking 1, 2, 3 | Should-BeCollection -Count 3 , but using just .Count sounds like a good solution, that is what we would have done in the assertion anyway, minus the problems with |.

Does the new Collect-Input approach make the collection vs single item array issue solvable?

No. We can tell when you pass the value by pipeline, or by parameter, but we cannot distinguish @(1) and 1 when passed by pipeline, because the internal collection does not distinguish that.

johlju commented 2 months ago

So... Will there be a Count parameter to Should-BeCollection or will we just update documentation to say that .Count should be used from now on? I'm good with either way, just want a hint so I know in what direction I should write the conversion code. 🙂

...but we cannot distinguish @(1) and 1...

Assuming this is already a problem in v5? I would expect that 1 would be equal to Should-BeCollection -Count 1 if it is passed to that command.

nohwnd commented 2 months ago

I will add -Count to Should-BeCollection, but please start with .Count, it will take me some time.