Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix line-based filter for tests with multiline testcases #1664

Merged
merged 16 commits into from
Sep 3, 2020
10 changes: 8 additions & 2 deletions src/Pester.Runtime.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ function New-Block {
[String] $Name,
[Parameter(Mandatory = $true)]
[ScriptBlock] $ScriptBlock,
[int] $StartLine,
nohwnd marked this conversation as resolved.
Show resolved Hide resolved
[String[]] $Tag = @(),
[HashTable] $FrameworkData = @{ },
[Switch] $Focus,
Expand Down Expand Up @@ -184,6 +185,7 @@ function New-Block {
$block.Path = $Path
$block.Tag = $Tag
$block.ScriptBlock = $ScriptBlock
$block.StartLine = $StartLine
fflaten marked this conversation as resolved.
Show resolved Hide resolved
$block.FrameworkData = $FrameworkData
$block.Focus = $Focus
$block.Id = $Id
Expand Down Expand Up @@ -369,6 +371,7 @@ function New-Test {
[String] $Name,
[Parameter(Mandatory = $true, Position = 1)]
[ScriptBlock] $ScriptBlock,
[int] $StartLine,
nohwnd marked this conversation as resolved.
Show resolved Hide resolved
[String[]] $Tag = @(),
[System.Collections.IDictionary] $Data = @{ },
[String] $Id,
Expand Down Expand Up @@ -397,6 +400,7 @@ function New-Test {
$test.ScriptBlock = $ScriptBlock
$test.Name = $Name
$test.Path = $path
$test.StartLine = $StartLine
$test.Tag = $Tag
$test.Focus = $Focus
$test.Skip = $Skip
Expand Down Expand Up @@ -1550,7 +1554,8 @@ function Test-ShouldRun {
# the test even if it is marked as skipped run this include as first so we figure it out
# in one place and check if parent was included after this one to short circuit the other
# filters in case parent already knows that it will run
$line = "$(if ($Item.ScriptBlock.File) { $Item.ScriptBlock.File } else { $Item.ScriptBlock.Id }):$($Item.ScriptBlock.StartPosition.StartLine)" -replace '\\', '/'

$line = "$(if ($Item.ScriptBlock.File) { $Item.ScriptBlock.File } else { $Item.ScriptBlock.Id }):$($Item.StartLine)" -replace '\\', '/'
if ($lineFilter -and 0 -ne $lineFilter.Count) {
$anyIncludeFilters = $true
foreach ($l in $lineFilter -replace '\\', '/') {
Expand Down Expand Up @@ -2344,6 +2349,7 @@ function New-ParametrizedTest () {
[String] $Name,
[Parameter(Mandatory = $true, Position = 1)]
[ScriptBlock] $ScriptBlock,
[int] $StartLine,
[String[]] $Tag = @(),
# do not use [hashtable[]] because that throws away the order if user uses [ordered] hashtable
[System.Collections.IDictionary[]] $Data = @{ },
Expand All @@ -2360,7 +2366,7 @@ function New-ParametrizedTest () {
$id = $ScriptBlock.StartPosition.StartLine
foreach ($d in $Data) {
# $innerId = if (-not $hasExternalId) { $null } else { "$Id-$(($counter++))" }
New-Test -Id $id -Name $Name -Tag $Tag -ScriptBlock $ScriptBlock -Data $d -Focus:$Focus -Skip:$Skip
New-Test -Id $id -Name $Name -Tag $Tag -ScriptBlock $ScriptBlock -StartLine $StartLine -Data $d -Focus:$Focus -Skip:$Skip
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/csharp/Pester/Block.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public Block()
public TimeSpan OwnDuration { get; set; }

public ScriptBlock ScriptBlock { get; set; }
public int StartLine { get; set; }
public Hashtable FrameworkData { get; set; } = new Hashtable();
public Hashtable PluginData { get; set; } = new Hashtable();

Expand All @@ -88,6 +89,7 @@ public Block()
public int OwnPendingCount { get; set; }
public int OwnNotRunCount { get; set; }
public int OwnInconclusiveCount { get; set; }

public override string ToString()
{
return ToStringConverter.BlockToString(this);
Expand Down
2 changes: 2 additions & 0 deletions src/csharp/Pester/Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public Test()
public bool Explicit { get; set; }
public bool ShouldRun { get; set; }

public int StartLine { get; set; }

public bool Executed { get; set; }
public DateTime? ExecutedAt { get; set; }
public bool Passed { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion src/functions/Context.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ https://pester.dev/docs/usage/testdrive
}

if ($ExecutionContext.SessionState.PSVariable.Get("invokedViaInvokePester")) {
New-Block -Name $Name -ScriptBlock $Fixture -Tag $Tag -FrameworkData @{ CommandUsed = "Context" } -Focus:$Focus -Skip:$Skip
New-Block -Name $Name -ScriptBlock $Fixture -StartLine $MyInvocation.ScriptLineNumber -Tag $Tag -FrameworkData @{ CommandUsed = "Context" } -Focus:$Focus -Skip:$Skip
}
else {
if ($invokedInteractively) {
Expand Down
2 changes: 1 addition & 1 deletion src/functions/Describe.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ about_TestDrive


if ($ExecutionContext.SessionState.PSVariable.Get('invokedViaInvokePester')) {
New-Block -Name $Name -ScriptBlock $Fixture -Tag $Tag -FrameworkData @{ CommandUsed = 'Describe' } -Focus:$Focus -Skip:$Skip
New-Block -Name $Name -ScriptBlock $Fixture -StartLine $MyInvocation.ScriptLineNumber -Tag $Tag -FrameworkData @{ CommandUsed = 'Describe' } -Focus:$Focus -Skip:$Skip
}
else {
Invoke-Interactively -CommandUsed 'Describe' -ScriptName $PSCmdlet.MyInvocation.ScriptName -SessionState $PSCmdlet.SessionState -BoundParameters $PSCmdlet.MyInvocation.BoundParameters
Expand Down
4 changes: 2 additions & 2 deletions src/functions/It.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,9 @@ about_should
}

if (any $TestCases) {
New-ParametrizedTest -Name $Name -ScriptBlock $Test -Data $TestCases -Tag $Tag -Focus:$Focus -Skip:$Skip
New-ParametrizedTest -Name $Name -ScriptBlock $Test -StartLine $MyInvocation.ScriptLineNumber -Data $TestCases -Tag $Tag -Focus:$Focus -Skip:$Skip
}
else {
New-Test -Name $Name -ScriptBlock $Test -Tag $Tag -Focus:$Focus -Skip:$Skip
New-Test -Name $Name -ScriptBlock $Test -StartLine $MyInvocation.ScriptLineNumber -Tag $Tag -Focus:$Focus -Skip:$Skip
}
}
4 changes: 2 additions & 2 deletions src/functions/Output.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ function Get-WriteScreenPlugin ($Verbosity) {
$text = $ReportStrings.$commandUsed -f $block.Name

if ($PesterPreference.Debug.ShowNavigationMarkers.Value) {
$text += ", $($block.ScriptBlock.File):$($block.ScriptBlock.StartPosition.StartLine)"
$text += ", $($block.ScriptBlock.File):$($block.StartLine)"
}

if (0 -eq $level -and -not $block.First) {
Expand Down Expand Up @@ -587,7 +587,7 @@ function Get-WriteScreenPlugin ($Verbosity) {
$humanTime = "$(Get-HumanTime ($_test.Duration)) ($(Get-HumanTime $_test.UserDuration)|$(Get-HumanTime $_test.FrameworkDuration))"

if ($PesterPreference.Debug.ShowNavigationMarkers.Value) {
$out += ", $($_test.ScriptBlock.File):$($_Test.ScriptBlock.StartPosition.StartLine)"
$out += ", $($_test.ScriptBlock.File):$($_Test.StartLine)"
}

$result = $_test.Result
Expand Down
32 changes: 29 additions & 3 deletions tst/Pester.RSpec.Configuration.ts.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ i -PassThru:$PassThru {
'slow' -notin $runTags | Verify-True
}

t "Filtering test based on line" {
t "Filtering test based on line of It" {
$c = [PesterConfiguration]@{
Run = @{
Path = "$PSScriptRoot/testProjects/BasicTests"
Expand All @@ -333,7 +333,7 @@ i -PassThru:$PassThru {
$tests[0].Name | Verify-Equal "fails"
}

t "Filtering test based on line" {
t "Filtering tests based on line of Describe" {
$c = [PesterConfiguration]@{
Run = @{
Path = "$PSScriptRoot/testProjects/BasicTests"
Expand All @@ -350,9 +350,35 @@ i -PassThru:$PassThru {
$r = Invoke-Pester -Configuration $c
$tests = @($r.Containers.Blocks.Tests | where { $_.ShouldRun })

$tests.Count | Verify-Equal 2
$tests.Count | Verify-Equal 4
$tests[0].Name | Verify-Equal "passing"
$tests[1].Name | Verify-Equal "fails"
$tests[2].Name | Verify-Equal "passing with testcases"
$tests[3].Name | Verify-Equal "passing with testcases"
}

t "Filtering test with testcases based on line of It" {
$c = [PesterConfiguration]@{
Run = @{
Path = "$PSScriptRoot/testProjects/BasicTests"
PassThru = $true
}
Filter = @{
Line = "$PSScriptRoot/testProjects/BasicTests/folder1/file1.Tests.ps1:12"
}
Output = @{
Verbosity = 'None'
}
}

$r = Invoke-Pester -Configuration $c
$tests = @($r.Containers.Blocks.Tests | where { $_.ShouldRun })

$tests.Count | Verify-Equal 2
$tests[0].Name | Verify-Equal "passing with testcases"
$tests[0].Data.Value | Verify-Equal 1
$tests[1].Name | Verify-Equal "passing with testcases"
$tests[1].Data.Value | Verify-Equal 2
}

t "Filtering test based on name will find the test" {
Expand Down
31 changes: 10 additions & 21 deletions tst/Pester.Runtime.ts.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ i -PassThru:$PassThru {
[System.Collections.IDictionary] $Data,
[String] $Id,
[ScriptBlock] $ScriptBlock,
[int] $StartLine,
[Switch] $Focus,
[Switch] $Skip
)
Expand All @@ -72,6 +73,7 @@ i -PassThru:$PassThru {
$t.Name = $Name
$t.Path = $Path
$t.Tag = $Tag
$t.StartLine = $StartLine
$t.Focus = [Bool]$Focus
$t.Skip = [Bool]$Skip
$t.Data = $Data
Expand Down Expand Up @@ -467,7 +469,7 @@ i -PassThru:$PassThru {
}

t "Given a test with file path and line number it includes it when it matches the lines filter" {
$t = New-TestObject -Name "test1" -ScriptBlock ($sb = { "test" })
$t = New-TestObject -Name "test1" -ScriptBlock ($sb = { "test" }) -StartLine $sb.StartPosition.StartLine

$f = New-FilterObject -Line "$($sb.File):$($sb.StartPosition.StartLine)"

Expand All @@ -476,7 +478,7 @@ i -PassThru:$PassThru {
}

t "Given a test with file path and line number it maybes it when it does not match the lines filter" {
$t = New-TestObject -Name "test1" -ScriptBlock { "test" }
$t = New-TestObject -Name "test1" -ScriptBlock { "test" } -StartLine 1

$f = New-FilterObject -Line "C:\file.tests.ps1:10"

Expand Down Expand Up @@ -537,25 +539,11 @@ i -PassThru:$PassThru {
}

t "re-runs failing tests" {
$sb = {
New-Block "block1" {
New-Test "test1" { "a" }
New-Block "block2" {
New-Test "test2" {
throw
}
}
}

New-Block "block3" {
New-Test "test3" {
if (-not $willPass) { throw }
}
}
}
# Tests stored in file to make StartLine predictable as it's needed for New-Block/-Test parameter for filtering to work
$testFile = "$PSScriptRoot/testProjects/RerunFailed.tests.ps1"

$willPass = $false
$pre = Invoke-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -ScriptBlock $sb)
$pre = Invoke-Test -SessionState $ExecutionContext.SessionState -BlockContainer (New-BlockContainerObject -Path $testFile)

# validate the precondition
$pre.Blocks[0].Tests[0].Executed | Verify-True
Expand All @@ -574,13 +562,14 @@ i -PassThru:$PassThru {
# here I have the failed tests, I need to accumulate paths
# on them and use them for filtering the run in the next run
# I should probably re-do the navigation to make it see how deep # I am in the scope, I have som Scopes prototype in the Mock imho
$lines = $pre | Where-Failed | % { "$($_.ScriptBlock.File):$($_.ScriptBlock.StartPosition.StartLine)" }

$lines = $pre | Where-Failed | % { "$($_.ScriptBlock.File):$($_.StartLine)" }
$lines.Length | Verify-Equal 2

Write-Host "`n`n`n"
# set the test3 to pass this time so we have some difference
$willPass = $true
$result = Invoke-Test -SessionState $ExecutionContext.SessionState -Filter (New-FilterObject -Line $lines ) -BlockContainer (New-BlockContainerObject -ScriptBlock $sb)
$result = Invoke-Test -SessionState $ExecutionContext.SessionState -Filter (New-FilterObject -Line $lines ) -BlockContainer (New-BlockContainerObject -Path $testFile)

$actual = @($result | View-Flat | where { $_.Executed })

Expand Down
7 changes: 7 additions & 0 deletions tst/testProjects/BasicTests/folder1/file1.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,11 @@ Describe "describe state tests" {
It "fails" {
1 | Should -Be 2
}

It "passing with testcases" -TestCases @(
@{Value = 1}
@{Value = 2}
) {
1 | Should -Be 1
}
}
16 changes: 16 additions & 0 deletions tst/testProjects/RerunFailed.tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Set-StrictMode -Version Latest

New-Block "rerun block1" -StartLine 3 {
New-Test "test1" -StartLine 4 { "a" }
New-Block "rerun block2" -StartLine 5 {
New-Test "test2" -StartLine 6 {
throw
}
}
}

New-Block "rerun block3" -StartLine 12 {
New-Test "test3" -StartLine 13 {
if (-not $willPass) { throw }
}
}