Writing tests for PowerShell functions

筅森魡賤 提交于 2019-12-11 19:13:10

问题


I have the following function (the function is an auxiliary function of an another function and it works correctly):

function Get-UserManager {
[CmdletBinding()]
param (
    [pscredential] $credential,
    [ValidateSet('ID')][string]$searchType,
    [string]$searchString,
)    

try {
    $reply = Invoke-RestMethod -Method Get -Uri $full_uri -Credentia $cred
} catch {
    Write-Verbose "Couldn't connect to the End Point"
    Write-Debug "$($_.Exception)"
    return $userListObject
}

$reply.elements | ForEach-Object {

    return $_    

  }

}

I am required to write a PowerShell test for the following function (The test must include all possible outputs, because I need the code coverage to be 100%).

Can someone please help me how do I write a PowerShell test that can check all the possible outputs of this function?

The test should be like this:

$moduleRoot = Resolve-Path "$PSScriptRoot\.."
$moduleName = Split-Path $moduleRoot -Leaf
$cred = Get-Credential

Describe "Demonstarting Code Coverage of: $moduleName" {

 It "Calls Function: get-UserManager" {
    {Get-UserManager -credential $cred -searchType ID -searchString 
    '12345' -delimiter} | Should Be $userListObject
}

}


回答1:


I assume you're using Pester, which is a Behaviour-Driven Development (BDD) framework. That is, it is designed to help you verify the behaviour of your code.

Ideally, you'd design the tests first according to the specification, then write the code, but as you already have the code, you'll need to think about possible ways it could be used and how you expect it to behave in each case. For example, looking at your code, what do you expect to happen if $searchString is empty or invalid credentials are passed? How can you test this actually happens?

Incidentally, code coverage is related to the execution paths in your code and just because you have 100% coverage, doesn't mean you have completely tested the code. For example, consider this basic function:

function Get-Product {
    Param (
        $Param1,
        $Param2
    )

    return $Param1 * $Param2
}

A single test that calls, say, Get-Product -Param1 12 -Param2 3 will have 100% code coverage as it tests all possible paths in the code, but it doesn't tell me how my code handles, for example, $Param1 being a string (e.g. "12") or one parameter is negative, etc, so I haven't really tested it thoroughly.




回答2:


Your code is currently non-functional, I assume because you reduced it to share on StackOverflow but have left some key elements out. For example $full_uri and $userListObject aren't populated but are used in the function and you have an extra comma in your param block.

That being said, you probably want to take the approach of using Mocking to simulate parts of your script so you can force different behaviour to occur and visit every path in order to get 100% code coverage. For example you need a test where the API returns an exception and enters your Catch block. That might look like this:

Describe "Demonstarting Code Coverage of: $moduleName" {

    Context 'Unable to connect to the endpoint' {

        Mock Invoke-RestMethod { Throw 'Endpoint unavailable' }
        Mock Write-Verbose
        Mock Write-Debug

        It 'Should enter the catch block when the endpoint returns an error' {
            Get-UserManager -Verbose -Debug
            Assert-MockCalled Write-Verbose -Times 1 -Exactly
            Assert-MockCalled Write-Debug -Times 1 -Exactly
        }
    }
}

If you're completely new to Pester, Mocking can be a tricky topic to get your head around at first. I recommend doing some learning on Pester first. I did a talk on Getting Started with Pester at PSDay last year that you might find informative.



来源:https://stackoverflow.com/questions/56223485/writing-tests-for-powershell-functions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!