pester/vscode-adapter

variable expansion not working in BeforeAll or BeforeEach blocks

Closed this issue · 5 comments

When running the following tests, the <title> value is never expanded in Test Explorer. The tests run properly when using invole-pester. Even if I set a static value for the title it will not show up in the test explorer pane.

# Discovers testing files
BeforeDiscovery {
      $files = Get-ChildItem '.\Definitions\policyDefinitions' -Recurse -Include *.json, *.jsonc 
}

# Expect multiple json in a loop, could be folder or file
# Print file name for each
Describe "Testing Policy Definition <title> " -ForEach $files {
    BeforeAll {
            $title=''
             $testJson = Get-Content $_.FullName -raw -ErrorAction SilentlyContinue
             if($(test-json $testJson)) {
             $title = (Get-Content $_ | ConvertFrom-Json).name
            }        
    }

        It "Json file <title> should be properly formatted" {
            $title | Should -Not -BeNullOrEmpty 
        }

}

image

@kevball2 confirmed, I simplified your example:

# Discovers testing files
BeforeDiscovery {
	$titles = 'a', 'b', 'c'
}

# Expect multiple json in a loop, could be folder or file
# Print file name for each
Describe 'Testing Title <title> ' -ForEach $titles {
	BeforeAll {
		$title = $_
	}

	It 'Title <title>' {}
}

We pull our titles from Pester, so this interpolation may be happening in Pester after our step in the process.

Your test formatting is kind of strange, looks like you are using named references (which refer to the properties on hashtables), and just by some quirk this works in Pester at the final output, but you are generating the "title" inside of the test, so it doesn't surprise me it doesn't discover correctly.

In order to do a named test with a named reference, you are supposed to use hashtables, it does not work with just objects: https://pester.dev/docs/usage/data-driven-tests

Try structuring your test this way:

# Discovers testing files
BeforeDiscovery {
	$files = Get-ChildItem "$PSScriptRoot/Mocks/PolicyDefinitions" -File -Recurse -Include *.json, *.jsonc
	$testCases = $files | ForEach-Object {
		@{
			File = $_
			Name = $_.BaseName
		}
	}
}

# Expect multiple json in a loop, could be folder or file
# Print file name for each
Describe 'Testing Policy Definition <name>' -ForEach $testCases {
	BeforeAll {
		$policy = Get-Content $file.FullName -Raw | ConvertFrom-Json -ErrorAction Stop
	}

	It 'should have a Name' {
		$policy.name | Should -Not -BeNullOrEmpty
	}
}

This works for me and has the desired result:
image

So unless I'm missing something, I'm going to close this as "wontfix" because it's not supported by Pester directly and it only works in your case probably due to a quirk.

Here's an alternative array syntax, which will ToString the file and give you the full filename, which doesn't look like what you want but I'm putting it here for posterity

# Discovers testing files
BeforeDiscovery {
	$files = Get-ChildItem "$PSScriptRoot/Mocks/PolicyDefinitions" -File -Recurse -Include *.json, *.jsonc
}

# Expect multiple json in a loop, could be folder or file
# Print file name for each
Describe 'Testing Policy Definition <_>' -ForEach $files {
	BeforeAll {
		$policy = Get-Content $_ -Raw | ConvertFrom-Json -ErrorAction Stop
	}

	It 'should have a Name' {
		$policy.name | Should -Not -BeNullOrEmpty
	}
}

Your test formatting is kind of strange, looks like you are using named references (which refer to the properties on hashtables), and just by some quirk this works in Pester at the final output, but you are generating the "title" inside of the test, so it doesn't surprise me it doesn't discover correctly.

In order to do a named test with a named reference, you are supposed to use hashtables, it does not work with just objects: https://pester.dev/docs/usage/data-driven-tests

Try structuring your test this way:

# Discovers testing files
BeforeDiscovery {
	$files = Get-ChildItem "$PSScriptRoot/Mocks/PolicyDefinitions" -File -Recurse -Include *.json, *.jsonc
	$testCases = $files | ForEach-Object {
		@{
			File = $_
			Name = $_.BaseName
		}
	}
}

# Expect multiple json in a loop, could be folder or file
# Print file name for each
Describe 'Testing Policy Definition <name>' -ForEach $testCases {
	BeforeAll {
		$policy = Get-Content $file.FullName -Raw | ConvertFrom-Json -ErrorAction Stop
	}

	It 'should have a Name' {
		$policy.name | Should -Not -BeNullOrEmpty
	}
}

This works for me and has the desired result: image

So unless I'm missing something, I'm going to close this as "wontfix" because it's not supported by Pester directly and it only works in your case probably due to a quirk.

Thanks for the feedback @JustinGrote! I was trying to reproduce the example from the pester documentation for the newer format for data driven tests - https://pester.dev/docs/usage/data-driven-tests#another-variation-on-foreach . Their example made me think it would be possible to set the title variable in the beforeAll block but that doesn't appear to work. In this instance the file name is all I wanted for the root test name so your example here creating the test cases does the job nicely.

Resolving issue: Solution for this issue was to create test cases in the BeforeDiscovery block that can be passed to the Describe block.