pester / Pester

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

Why pester runs a source script before executing test? #658

Closed IvanovOleg closed 7 years ago

IvanovOleg commented 7 years ago

Hi, Source.ps1

function Clean {

}

$test = 5
$test

Source.Tests.ps1

$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
. "$here\$sut"

Describe "Clean" {
    It "does something useful" {
        $result = Clean
        $result | Should Be $false
    }
}

Output:

5 Describing Clean [-] does something useful 31ms Expected: {False} But was: {} 8: $result | Should Be $false в Should, C:\Program Files\WindowsPowerShell\Modules\Pester\3.4.0\Functions\Assertions\Should.ps1: строка 92 в , C:\Users\dlj\Documents\powershell_tutorial\tests\Source.Tests.ps1: строка 8 в Invoke-Test, C:\Program Files\WindowsPowerShell\Modules\Pester\3.4.0\Functions\It.ps1: строка 253 в ItImpl, C:\Program Files\WindowsPowerShell\Modules\Pester\3.4.0\Functions\It.ps1: строка 203 в It, C:\Program Files\WindowsPowerShell\Modules\Pester\3.4.0\Functions\It.ps1: строка 117 в , C:\Users\dlj\Documents\powershell_tutorial\tests\Source.Tests.ps1: строка 6 в Describe, C:\Program Files\WindowsPowerShell\Modules\Pester\3.4.0\Functions\Describe.ps1: строка 100 в , C:\Users\dlj\Documents\powershell_tutorial\tests\Source.Tests.ps1: строка 5 в , C:\Program Files\WindowsPowerShell\Modules\Pester\3.4.0\Pester.psm1: строка 297 в Invoke-Pester, C:\Program Files\WindowsPowerShell\Modules\Pester\3.4.0\Pester.psm1: строка 310 в , <Нет файла>: строка 1 Tests completed in 31ms Passed: 0 Failed: 1 Skipped: 0 Pending: 0 Inconclusive: 0

Why does pester show "5"? I don't want to execute $test = 5 and $test, I just want to test the clean function and thats all. If I disable . "$here\$sut" than it can't find a function. Is it possible to test such script partially?

nohwnd commented 7 years ago

Because that is how dot sourcing works. By saying . "$here\$sut" you instruct powershell to run the script. It runs almost the same way as if you just invoked it normally (for example by the & operator). The difference is that instead of creating a new scope, it runs in the current scope, leaving behind all the defined fumctions and variables. We use this feature to import the functions and variables from the tested script to the test script, but it also runs all the other statements in the script. That's why your script outputs the number 5.

There is no built in way to run just the functions of a script (at least none that I know of), so you either have to put the main executable code in "if ($underTest)" and provide the parameter when testing, or do a variation on the same thing but using a different condition, such as checking if the code is being dot-sourced.

nohwnd commented 7 years ago

My web is down, but here is a copy of an aricle that I wrote on the topic a while ago. http://web.archive.org/web/20160112151907/http://jakubjares.com/blog/2015/01/10/test-powershell-scripts-end-to-end-with-pester/

IvanovOleg commented 7 years ago

@nohwnd , thank you!