2

I have the following Pester Test-script:

function Get-Name{
    return "TestObject"
}

Describe{
    BeforeAll{
        $Script:ObjectID
        $API::[API]::New()
    }

    It 'Get ObjectID By NAME'{
        $Name = Get-Name
        $Object = $API.GetObjectByName($Name)
        $ObjectID = $Object.id
        $ObjectID | Should -BeGreaterThan 0
        Write-Host "ObjectID = " + $ObjectID
    }

    It 'Print Object ID'{
        write-host $ObjectID 
    }
}

My issue is the following:

Issue 1: Function not recognized when the script is 'invoked'.

Whenever I run the script with the Invoke-Pester -Path c:\path\test.ps1 -Detailed -command, my first test fails due to the function not being recognized. However, when I compile and run my script in PowerShell ISE, the first test succeeds.

Issue 2: Pass ObjectID to another It-block My second test never outputs the ID retrieved from the first test. I do not know how to pass the variable from one test, to another. I already have tried putting the BeforeALl above the Describe but without success.

What am I doing wrong in both cases? My pester version is 5.6.1

4
  • 1
    I assume by Invoke-Command you meant Invoke-Pester ? As for "Issue 2" whats the point of this test? What is it trying to assert? It blocks are supposed to be isolated tests, there shouldn't be a relation between 2 It blocks Commented Jul 17, 2024 at 15:25
  • @SantiagoSquarzon Thanks for your command. Yes I meant Invoke-Pester and I must not be the first one trying to pass variables between It-blocks right? What is the purpose of Script-wide variables then? thanks. It's important because in one script I might create and object (CreateObject()-method in API) and use its ID in another test (CreateOtherObject() with an API-call that 'builds' on the previous one. Commented Jul 17, 2024 at 15:32
  • 1
    I don't know if you're the first one but it is not the way to do it. You can use scope modifiers if you want to, I don't see the point of it. Tests should be isolated from one another Commented Jul 17, 2024 at 15:39
  • @SantiagoSquarzon Thanks! OK but let's say in my case I have an API function I would like to test named CreateUser() and a second API function named UpdateUser(). Wouldn't it be smart to test and have 2 seperate tests and see if both functions work correctly? My UpdateUser()-function would in this case 'depend' on the userID I got from CreateUser(). Commented Jul 17, 2024 at 15:41

1 Answer 1

3

For issue 1, the most commonly used option is to have a psm1 in the same folder as your tests scripts where you have all the functions needed for them, for example:

  • common.psm1
function Get-Name {
    return "TestObject"
}

# Other functions used in all Pester Tests

Then in your .tests.ps1 file you can use Import-Module:

$common = Join-Path $PSScriptRoot -ChildPath common.psm1
Import-Module $common

Describe .... {

}

The other option is to use a scope modifier if you want to have the function in the same file as the test. See about Scopes for details.

function global:Get-Name {
    return "TestObject"
}

Describe .... {

}

For issue 2, as stated in comments, It blocks should be isolated from one another, you should ideally first assert your Get... works then, in your next test and since you have already asserted it worked, you can Get... again and then assert Update... works, and so on. Of course this might slow down your tests but the point is to ensure it works not that it is fast.

This is an example of a commonly used pattern:

function script:Get-Name {
    return 'TestObject'
}

Describe 'My Module' {
    Context 'Get Thing' {
        It 'Get Object' {
            Get-Name | Should -Be 'TestObject'
        }
    }

    Context 'Do stuff that depends on Get Thing' {
        BeforeAll {
            # now that we asserted that Get works,
            # we can use it for next tests:
            $foo = Get-Name
        }

        It 'Update Object' {
            $foo + ' hello' | Should -Be 'TestObject hello'
        }

        It 'does other stuff with `$foo`' {
            # ...
        }
    }
}

If you must pass an object from one block to the other you can, again, use a scope modifier:

function script:Get-Name {
    return 'TestObject'
}

Describe 'Some tests' {
    It 'Get Object' {
        Get-Name | Should -Be 'TestObject'
        $script:foo = Get-Name
    }

    It 'Update Object' {
        $foo + ' hello' | Should -Be 'TestObject hello'
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

@user3127554 I have updated the wording to make it more clear what I'd personally do as opposed to passing objects from one It block to the other

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.