Permalink
Fetching contributors…
Cannot retrieve contributors at this time
378 lines (329 sloc) 13.8 KB
function New-PesterState
{
param (
[String[]]$TagFilter,
[String[]]$ExcludeTagFilter,
[String[]]$TestNameFilter,
[System.Management.Automation.SessionState]$SessionState,
[Switch]$Strict,
[Pester.OutputTypes]$Show = 'All',
[object]$PesterOption,
[Switch]$RunningViaInvokePester
)
if ($null -eq $SessionState) { $SessionState = $ExecutionContext.SessionState }
if ($null -eq $PesterOption)
{
$PesterOption = New-PesterOption
}
elseif ($PesterOption -is [System.Collections.IDictionary])
{
try
{
$PesterOption = New-PesterOption @PesterOption
}
catch
{
throw
}
}
& $SafeCommands['New-Module'] -Name Pester -AsCustomObject -ArgumentList $TagFilter, $ExcludeTagFilter, $TestNameFilter, $SessionState, $Strict, $Show, $PesterOption, $RunningViaInvokePester -ScriptBlock {
param (
[String[]]$_tagFilter,
[String[]]$_excludeTagFilter,
[String[]]$_testNameFilter,
[System.Management.Automation.SessionState]$_sessionState,
[Switch]$Strict,
[Pester.OutputTypes]$Show,
[object]$PesterOption,
[Switch]$RunningViaInvokePester
)
#public read-only
$TagFilter = $_tagFilter
$ExcludeTagFilter = $_excludeTagFilter
$TestNameFilter = $_testNameFilter
$script:SessionState = $_sessionState
$script:Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
$script:MostRecentTimestamp = 0
$script:CommandCoverage = @()
$script:Strict = $Strict
$script:Show = $Show
$script:InTest = $false
$script:TestResult = @()
$script:TotalCount = 0
$script:Time = [timespan]0
$script:PassedCount = 0
$script:FailedCount = 0
$script:SkippedCount = 0
$script:PendingCount = 0
$script:InconclusiveCount = 0
$script:IncludeVSCodeMarker = $PesterOption.IncludeVSCodeMarker
$script:TestSuiteName = $PesterOption.TestSuiteName
$script:RunningViaInvokePester = $RunningViaInvokePester
$script:SafeCommands = @{}
$script:SafeCommands['New-Object'] = & (Pester\SafeGetCommand) -Name New-Object -Module Microsoft.PowerShell.Utility -CommandType Cmdlet
$script:SafeCommands['Select-Object'] = & (Pester\SafeGetCommand) -Name Select-Object -Module Microsoft.PowerShell.Utility -CommandType Cmdlet
$script:SafeCommands['Export-ModuleMember'] = & (Pester\SafeGetCommand) -Name Export-ModuleMember -Module Microsoft.PowerShell.Core -CommandType Cmdlet
$script:SafeCommands['Add-Member'] = & (Pester\SafeGetCommand) -Name Add-Member -Module Microsoft.PowerShell.Utility -CommandType Cmdlet
function New-TestGroup([string] $Name, [string] $Hint)
{
& $SafeCommands['New-Object'] psobject -Property @{
Name = $Name
Type = 'TestGroup'
Hint = $Hint
Actions = [System.Collections.ArrayList]@()
BeforeEach = & $SafeCommands['New-Object'] System.Collections.Generic.List[scriptblock]
AfterEach = & $SafeCommands['New-Object'] System.Collections.Generic.List[scriptblock]
BeforeAll = & $SafeCommands['New-Object'] System.Collections.Generic.List[scriptblock]
AfterAll = & $SafeCommands['New-Object'] System.Collections.Generic.List[scriptblock]
TotalCount = 0
Time = [timespan]0
PassedCount = 0
FailedCount = 0
SkippedCount = 0
PendingCount = 0
InconclusiveCount = 0
}
}
$script:TestActions = New-TestGroup -Name Pester -Hint Root
$script:TestGroupStack = & $SafeCommands['New-Object'] System.Collections.Stack
$script:TestGroupStack.Push($script:TestActions)
function EnterTestGroup([string] $Name, [string] $Hint)
{
$newGroup = New-TestGroup @PSBoundParameters
$null = $script:TestGroupStack.Peek().Actions.Add($newGroup)
$script:TestGroupStack.Push($newGroup)
}
function LeaveTestGroup([string] $Name, [string] $Hint)
{
$currentGroup = $script:TestGroupStack.Pop()
if ($currentGroup.Name -ne $Name -or $currentGroup.Hint -ne $Hint)
{
throw "TestGroups stack corrupted: Expected name/hint of '$Name','$Hint'. Found '$($currentGroup.Name)', '$($currentGroup.Hint)'."
}
}
function AddTestResult
{
param (
[string]$Name,
[ValidateSet("Failed","Passed","Skipped","Pending","Inconclusive")]
[string]$Result,
[Nullable[TimeSpan]]$Time,
[string]$FailureMessage,
[string]$StackTrace,
[string] $ParameterizedSuiteName,
[System.Collections.IDictionary] $Parameters,
[System.Management.Automation.ErrorRecord] $ErrorRecord
)
# defining this function in here, because otherwise it is not available
function New-ErrorRecord ([string] $Message, [string] $ErrorId, [string] $File, [string] $Line, [string] $LineText) {
$exception = & $SafeCommands['New-Object'] Exception $Message
$errorCategory = [Management.Automation.ErrorCategory]::InvalidResult
# we use ErrorRecord.TargetObject to pass structured information about the error to a reporting system.
$targetObject = @{Message = $Message; File = $File; Line = $Line; LineText = $LineText}
$errorRecord = & $SafeCommands['New-Object'] Management.Automation.ErrorRecord $exception, $ErrorID, $errorCategory, $targetObject
return $errorRecord
}
$previousTime = $script:MostRecentTimestamp
$script:MostRecentTimestamp = $script:Stopwatch.Elapsed
if ($null -eq $Time)
{
$Time = $script:MostRecentTimestamp - $previousTime
}
if (-not $script:Strict)
{
$Passed = "Passed","Skipped","Pending" -contains $Result
}
else
{
$Passed = $Result -eq "Passed"
if (($Result -eq "Skipped") -or ($Result -eq "Pending"))
{
$FailureMessage = "The test failed because the test was executed in Strict mode and the result '$result' was translated to Failed."
$ErrorRecord = New-ErrorRecord -ErrorId 'PesterTestInconclusive' -Message $FailureMessage
$Result = "Failed"
}
}
$script:TotalCount++
$script:Time += $Time
switch ($Result)
{
Passed { $script:PassedCount++; break; }
Failed { $script:FailedCount++; break; }
Skipped { $script:SkippedCount++; break; }
Pending { $script:PendingCount++; break; }
Inconclusive { $script:InconclusiveCount++; break; }
}
$resultRecord = & $SafeCommands['New-Object'] -TypeName PsObject -Property @{
Name = $Name
Type = 'TestCase'
Passed = $Passed
Result = $Result
Time = $Time
FailureMessage = $FailureMessage
StackTrace = $StackTrace
ErrorRecord = $ErrorRecord
ParameterizedSuiteName = $ParameterizedSuiteName
Parameters = $Parameters
Show = $script:Show
}
$null = $script:TestGroupStack.Peek().Actions.Add($resultRecord)
# Attempting some degree of backward compatibility for the TestResult collection for now; deprecated and will be removed in the future
$describe = ''
$contexts = [System.Collections.ArrayList]@()
# make a copy of the stack and reverse it
$reversedStack = $script:TestGroupStack.ToArray()
[array]::Reverse($reversedStack)
foreach ($group in $reversedStack)
{
if ($group.Hint -eq 'Root' -or $group.Hint -eq 'Script') { continue }
if ($describe -eq '')
{
$describe = $group.Name
}
else
{
$null = $contexts.Add($group.Name)
}
}
$context = $contexts -join '\'
$script:TestResult += & $SafeCommands['New-Object'] psobject -Property @{
Describe = $describe
Context = $context
Name = $Name
Passed = $Passed
Result = $Result
Time = $Time
FailureMessage = $FailureMessage
StackTrace = $StackTrace
ErrorRecord = $ErrorRecord
ParameterizedSuiteName = $ParameterizedSuiteName
Parameters = $Parameters
Show = $script:Show
}
}
function AddSetupOrTeardownBlock([scriptblock] $ScriptBlock, [string] $CommandName)
{
$currentGroup = $script:TestGroupStack.Peek()
$isSetupCommand = IsSetupCommand -CommandName $CommandName
$isGroupCommand = IsTestGroupCommand -CommandName $CommandName
if ($isSetupCommand)
{
if ($isGroupCommand)
{
$currentGroup.BeforeAll.Add($ScriptBlock)
}
else
{
$currentGroup.BeforeEach.Add($ScriptBlock)
}
}
else
{
if ($isGroupCommand)
{
$currentGroup.AfterAll.Add($ScriptBlock)
}
else
{
$currentGroup.AfterEach.Add($ScriptBlock)
}
}
}
function IsSetupCommand
{
param ([string] $CommandName)
return $CommandName -eq 'BeforeEach' -or $CommandName -eq 'BeforeAll'
}
function IsTestGroupCommand
{
param ([string] $CommandName)
return $CommandName -eq 'BeforeAll' -or $CommandName -eq 'AfterAll'
}
function GetTestCaseSetupBlocks
{
$blocks = @(
foreach ($group in $this.TestGroups)
{
$group.BeforeEach
}
)
return $blocks
}
function GetTestCaseTeardownBlocks
{
$groups = @($this.TestGroups)
[Array]::Reverse($groups)
$blocks = @(
foreach ($group in $groups)
{
$group.AfterEach
}
)
return $blocks
}
function GetCurrentTestGroupSetupBlocks
{
return $script:TestGroupStack.Peek().BeforeAll
}
function GetCurrentTestGroupTeardownBlocks
{
return $script:TestGroupStack.Peek().AfterAll
}
function EnterTest
{
if ($script:InTest)
{
throw 'You are already in a test case.'
}
$script:InTest = $true
}
function LeaveTest
{
$script:InTest = $false
}
$ExportedVariables = "TagFilter",
"ExcludeTagFilter",
"TestNameFilter",
"TestResult",
"SessionState",
"CommandCoverage",
"Strict",
"Show",
"Time",
"TotalCount",
"PassedCount",
"FailedCount",
"SkippedCount",
"PendingCount",
"InconclusiveCount",
"IncludeVSCodeMarker",
"TestActions",
"TestGroupStack",
"TestSuiteName",
"InTest",
"RunningViaInvokePester"
$ExportedFunctions = "EnterTestGroup",
"LeaveTestGroup",
"AddTestResult",
"AddSetupOrTeardownBlock",
"GetTestCaseSetupBlocks",
"GetTestCaseTeardownBlocks",
"GetCurrentTestGroupSetupBlocks",
"GetCurrentTestGroupTeardownBlocks",
"EnterTest",
"LeaveTest"
& $SafeCommands['Export-ModuleMember'] -Variable $ExportedVariables -function $ExportedFunctions
} |
& $SafeCommands['Add-Member'] -PassThru -MemberType ScriptProperty -Name CurrentTestGroup -Value {
$this.TestGroupStack.Peek()
} |
& $SafeCommands['Add-Member'] -PassThru -MemberType ScriptProperty -Name TestGroups -Value {
$array = $this.TestGroupStack.ToArray()
[Array]::Reverse($array)
return $array
} |
& $SafeCommands['Add-Member'] -PassThru -MemberType ScriptProperty -Name IndentLevel -Value {
# We ignore the root node of the stack here, and don't start indenting until after the Script nodes inside the root
return [Math]::Max(0, $this.TestGroupStack.Count - 2)
}
}