diff --git a/Functions/Output.Tests.ps1 b/Functions/Output.Tests.ps1 new file mode 100644 index 000000000..0df400e7f --- /dev/null +++ b/Functions/Output.Tests.ps1 @@ -0,0 +1,57 @@ +InModuleScope -ModuleName Pester -ScriptBlock { + Describe 'Has-Flag' -Fixture { + It 'Returns true when setting and value are the same' { + $setting = [Pester.OutputTypes]::Passed + $value = [Pester.OutputTypes]::Passed + + $value | Has-Flag $setting | Should Be $true + } + + It 'Returns false when setting and value are the different' { + $setting = [Pester.OutputTypes]::Passed + $value = [Pester.OutputTypes]::Failed + + $value | Has-Flag $setting | Should Be $false + } + + It 'Returns true when setting contains value' { + $setting = [Pester.OutputTypes]::Passed -bor [Pester.OutputTypes]::Failed + $value = [Pester.OutputTypes]::Passed + + $value | Has-Flag $setting | Should Be $true + } + + It 'Returns false when setting does not contain the value' { + $setting = [Pester.OutputTypes]::Passed -bor [Pester.OutputTypes]::Failed + $value = [Pester.OutputTypes]::Summary + + $value | Has-Flag $setting | Should Be $false + } + + It 'Returns true when at least one setting is contained in value' { + $setting = [Pester.OutputTypes]::Passed -bor [Pester.OutputTypes]::Failed + $value = [Pester.OutputTypes]::Summary -bor [Pester.OutputTypes]::Failed + + $value | Has-Flag $setting | Should Be $true + } + + It 'Returns false when none of settings is contained in value' { + $setting = [Pester.OutputTypes]::Passed -bor [Pester.OutputTypes]::Failed + $value = [Pester.OutputTypes]::Summary -bor [Pester.OutputTypes]::Describe + + $value | Has-Flag $setting | Should Be $false + } + } + + Describe 'Default OutputTypes' -Fixture { + It 'Fails output type contains all except passed' { + $expected = [Pester.OutputTypes]'Default, Failed, Pending, Skipped, Inconclusive, Describe, Context, Summary' + [Pester.OutputTypes]::Fails | Should Be $expected + } + + It 'All output type contains all flags' { + $expected = [Pester.OutputTypes]'Default, Passed, Failed, Pending, Skipped, Inconclusive, Describe, Context, Summary' + [Pester.OutputTypes]::All | Should Be $expected + } + } +} diff --git a/Functions/PesterState.ps1 b/Functions/PesterState.ps1 index 560cb27a6..44097a47c 100644 --- a/Functions/PesterState.ps1 +++ b/Functions/PesterState.ps1 @@ -6,7 +6,7 @@ function New-PesterState [String[]]$TestNameFilter, [System.Management.Automation.SessionState]$SessionState, [Switch]$Strict, - [Switch]$Quiet, + [Pester.OutputTypes]$Show = 'All', [object]$PesterOption ) @@ -35,7 +35,7 @@ function New-PesterState [String[]]$_testNameFilter, [System.Management.Automation.SessionState]$_sessionState, [Switch]$Strict, - [Switch]$Quiet, + [Pester.OutputTypes]$Show, [object]$PesterOption ) @@ -56,7 +56,7 @@ function New-PesterState $script:BeforeAll = @() $script:AfterAll = @() $script:Strict = $Strict - $script:Quiet = $Quiet + $script:Show = $Show $script:TestResult = @() @@ -223,7 +223,7 @@ function New-PesterState "BeforeAll", "AfterAll", "Strict", - "Quiet", + "Show", "Time", "TotalCount", "PassedCount", @@ -242,7 +242,7 @@ function New-PesterState "AddTestResult" & $SafeCommands['Export-ModuleMember'] -Variable $ExportedVariables -function $ExportedFunctions - } -ArgumentList $TagFilter, $ExcludeTagFilter, $TestNameFilter, $SessionState, $Strict, $Quiet, $PesterOption | + } -ArgumentList $TagFilter, $ExcludeTagFilter, $TestNameFilter, $SessionState, $Strict, $Show, $PesterOption | & $SafeCommands['Add-Member'] -MemberType ScriptProperty -Name Scope -Value { if ($this.CurrentTest) { 'It' } elseif ($this.CurrentContext) { 'Context' } @@ -273,7 +273,7 @@ function Write-Describe [Parameter(mandatory=$true, valueFromPipeline=$true)]$Name ) process { - Write-Screen Describing $Name -OutputType Header + Write-Screen Describing $Name -OutputType Describe } } @@ -284,7 +284,7 @@ function Write-Context ) process { $margin = " " * 3 - Write-Screen ${margin}Context $Name -OutputType Header + Write-Screen ${margin}Context $Name -OutputType Context } } @@ -426,13 +426,13 @@ function Write-PesterReport $PesterState ) - Write-Screen "Tests completed in $(Get-HumanTime $PesterState.Time.TotalSeconds)" + Write-Screen "Tests completed in $(Get-HumanTime $PesterState.Time.TotalSeconds)" -OutputType "Summary" Write-Screen ("Passed: {0} Failed: {1} Skipped: {2} Pending: {3} Inconclusive: {4}" -f $PesterState.PassedCount, $PesterState.FailedCount, $PesterState.SkippedCount, $PesterState.PendingCount, - $PesterState.InconclusiveCount) + $PesterState.InconclusiveCount) -OutputType "Summary" } function Write-Screen { @@ -444,20 +444,26 @@ function Write-Screen { [Switch] $NoNewline, [Object] $Separator, #custom parameters - [Switch] $Quiet = $pester.Quiet, - [ValidateSet("Failed","Passed","Skipped","Pending","Inconclusive","Header","Standard")] - [String] $OutputType = "Standard" + [Pester.OutputTypes] $OutputFilter = $pester.Show, + [Pester.OutputTypes] $OutputType = 'Default' ) begin { - if ($Quiet) { return } + $quiet = $OutputFilter -eq [Pester.OutputTypes]::None + $writeToScreen = $OutputFilter | Has-Flag $OutputType + $skipOutput = $quiet -or (-not $writeToScreen) + + if ($skipOutput) + { + return + } #make the bound parameters compatible with Write-Host - if ($PSBoundParameters.ContainsKey('Quiet')) { $PSBoundParameters.Remove('Quiet') | & $SafeCommands['Out-Null'] } + if ($PSBoundParameters.ContainsKey('OutputFilter')) { $PSBoundParameters.Remove('OutputFilter') | & $SafeCommands['Out-Null'] } if ($PSBoundParameters.ContainsKey('OutputType')) { $PSBoundParameters.Remove('OutputType') | & $SafeCommands['Out-Null'] } - if ($OutputType -ne "Standard") + if (-not ($OutputType | Has-Flag 'Default, Summary')) { #create the key first to make it work in strict mode if (-not $PSBoundParameters.ContainsKey('ForegroundColor')) @@ -465,8 +471,6 @@ function Write-Screen { $PSBoundParameters.Add('ForegroundColor', $null) } - - switch ($Host.Name) { #light background @@ -477,7 +481,8 @@ function Write-Screen { Skipped = [ConsoleColor]::DarkGray Pending = [ConsoleColor]::DarkCyan Inconclusive = [ConsoleColor]::DarkCyan - Header = [ConsoleColor]::Magenta + Describe = [ConsoleColor]::Magenta + Context = [ConsoleColor]::Magenta } } #dark background @@ -488,7 +493,8 @@ function Write-Screen { Skipped = [ConsoleColor]::Gray Pending = [ConsoleColor]::Cyan Inconclusive = [ConsoleColor]::Cyan - Header = [ConsoleColor]::Magenta + Describe = [ConsoleColor]::Magenta + Context = [ConsoleColor]::Magenta } } default { @@ -498,14 +504,15 @@ function Write-Screen { Skipped = [ConsoleColor]::Gray Pending = [ConsoleColor]::Gray Inconclusive = [ConsoleColor]::Gray - Header = [ConsoleColor]::Magenta + Describe = [ConsoleColor]::Magenta + Context = [ConsoleColor]::Magenta } } } - - $PSBoundParameters.ForegroundColor = $ColorSet.$OutputType + # the output type must be forced to become string, otherwise the color is not found + $PSBoundParameters.ForegroundColor = $ColorSet[$OutputType.ToString()] } try { @@ -525,7 +532,7 @@ function Write-Screen { process { - if ($Quiet) { return } + if ($skipOutput) { return } try { $steppablePipeline.Process($_) } catch { @@ -535,7 +542,7 @@ function Write-Screen { end { - if ($Quiet) { return } + if ($skipOutput) { return } try { $steppablePipeline.End() } catch { diff --git a/Pester.psm1 b/Pester.psm1 index d360e724c..055170871 100644 --- a/Pester.psm1 +++ b/Pester.psm1 @@ -115,6 +115,42 @@ $moduleRoot = & $script:SafeCommands['Split-Path'] -Path $MyInvocation.MyCommand & $script:SafeCommands['Where-Object'] { -not ($_.ProviderPath.ToLower().Contains(".tests.")) } | & $script:SafeCommands['ForEach-Object'] { . $_.ProviderPath } +Add-Type -TypeDefinition @" +using System; + +namespace Pester +{ + [Flags] + public enum OutputTypes + { + None = 0, + Default = 1, + Passed = 2, + Failed = 4, + Pending = 8, + Skipped = 16, + Inconclusive = 32, + Describe = 64, + Context = 128, + Summary = 256, + All = Default | Passed | Failed | Pending | Skipped | Inconclusive | Describe | Context | Summary, + Fails = Default | Failed | Pending | Skipped | Inconclusive | Describe | Context | Summary + } +} +"@ + +function Has-Flag { + param + ( + [Parameter(Mandatory = $true)] + $Setting, + [Parameter(Mandatory = $true, ValueFromPipeline=$true)] + $Value + ) + + 0 -ne ($Setting -band $Value) +} + function Invoke-Pester { <# .SYNOPSIS @@ -419,7 +455,9 @@ New-PesterOption [Switch]$Quiet, - [object]$PesterOption + [object]$PesterOption, + + [Pester.OutputTypes]$Show = 'All' ) if ($PSBoundParameters.ContainsKey('OutputXml')) @@ -434,7 +472,12 @@ New-PesterOption $script:mockTable = @{} - $pester = New-PesterState -TestNameFilter $TestName -TagFilter ($Tag -split "\s") -ExcludeTagFilter ($ExcludeTag -split "\s") -SessionState $PSCmdlet.SessionState -Strict:$Strict -Quiet:$Quiet -PesterOption $PesterOption + if ($Quiet) + { + $Show = [Pester.OutputTypes]::None + } + + $pester = New-PesterState -TestNameFilter $TestName -TagFilter ($Tag -split "\s") -ExcludeTagFilter ($ExcludeTag -split "\s") -SessionState $PSCmdlet.SessionState -Strict:$Strict -Show:$Show -PesterOption $PesterOption Enter-CoverageAnalysis -CodeCoverage $CodeCoverage -PesterState $pester Write-Screen "`r`n`r`n`r`n`r`n"