diff --git a/.gitattributes b/.gitattributes
index 69bc95b2d..84f736dfc 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,3 +1,12 @@
# Auto detect text files and perform LF normalization
-* text=auto
-*.ps1 text
\ No newline at end of file
+* text=auto eol=crlf
+*.ps1 text
+*.psm1 text
+*.psd1 text
+*.ps1xml text
+*.md text
+*.feature text
+*.xsd text
+*.dtd text
+*.dll binary
+*.PNG binary
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000..18e3c6647
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,25 @@
+
+language: generic
+
+matrix:
+ include:
+ - os: osx
+ osx_image: xcode9.1
+ before_install:
+ - brew update
+ - brew tap caskroom/cask
+ - brew cask install powershell
+ - os: linux
+ dist: trusty
+ # VM-based builds turned out to be faster
+ sudo: required
+ addons:
+ apt:
+ sources:
+ - sourceline: deb [arch=amd64] https://packages.microsoft.com/ubuntu/14.04/prod trusty main
+ key_url: https://packages.microsoft.com/keys/microsoft.asc
+ packages:
+ - powershell
+
+script:
+ - pwsh -c 'Import-Module ./Pester.psd1; Invoke-Pester -ExcludeTag VersionChecks -EnableExit'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fb0a1e223..98f6f2fea 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,6 @@
## Unreleased
- Add-AssertionOperator can be called multiple times for identical parameters without errors. [GH-893]
+ - Support for PowerShell Core on Windows, Linux and macOS added [GH-639]
## 4.0.8 (September 15, 2017)
- Add Assert-VerifiableMocks that throws [GH-881]
diff --git a/Functions/Assertions/Be.Tests.ps1 b/Functions/Assertions/Be.Tests.ps1
index 57699129a..da836743b 100644
--- a/Functions/Assertions/Be.Tests.ps1
+++ b/Functions/Assertions/Be.Tests.ps1
@@ -91,13 +91,17 @@ InModuleScope Pester {
$doc | Should be $doc
}
- It 'throws exception when self-imposed recursion limit is reached' {
- $a1 = @(0,1)
- $a2 = @($a1,2)
- $a1[0] = $a2
+ # The test excluded on macOS due to issue https://github.com/PowerShell/PowerShell/issues/4268
+ If ((GetPesterOS) -ne 'macOS') {
+ It 'throws exception when self-imposed recursion limit is reached' {
+ $a1 = @(0,1)
+ $a2 = @($a1,2)
+ $a1[0] = $a2
- { $a1 | Should be $a2 } | Should throw 'recursion depth limit'
+ { $a1 | Should be $a2 } | Should throw 'recursion depth limit'
+ }
}
+
}
Describe "PesterBeFailureMessage" {
diff --git a/Functions/Assertions/FileContentMatch.Tests.ps1 b/Functions/Assertions/FileContentMatch.Tests.ps1
index e3237aecc..f4f175646 100644
--- a/Functions/Assertions/FileContentMatch.Tests.ps1
+++ b/Functions/Assertions/FileContentMatch.Tests.ps1
@@ -3,7 +3,7 @@
InModuleScope Pester {
Describe "PesterFileContentMatch" {
Context "when testing file contents" {
- Setup -File "test.txt" "this is line 1`nrush is awesome`nAnd this is Unicode: ☺"
+ Setup -File "test.txt" "this is line 1$([System.Environment]::NewLine)rush is awesome$([System.Environment]::NewLine)And this is Unicode: ☺"
It "returns true if the file contains the specified content" {
"$TestDrive\test.txt" | Should FileContentMatch rush
diff --git a/Functions/Assertions/FileContentMatchExactly.Tests.ps1 b/Functions/Assertions/FileContentMatchExactly.Tests.ps1
index 6db422abf..1ebb9a851 100644
--- a/Functions/Assertions/FileContentMatchExactly.Tests.ps1
+++ b/Functions/Assertions/FileContentMatchExactly.Tests.ps1
@@ -3,7 +3,7 @@
InModuleScope Pester {
Describe "PesterFileContentMatchExactly" {
Context "when testing file contents" {
- Setup -File "test.txt" "this is line 1`nPester is awesome`nAnd this is Unicode: ☺"
+ Setup -File "test.txt" "this is line 1$([System.Environment]::NewLine)Pester is awesome$([System.Environment]::NewLine)And this is Unicode: ☺"
It "returns true if the file contains the specified content exactly" {
"$TestDrive\test.txt" | Should FileContentMatchExactly Pester
"$TestDrive\test.txt" | Should -FileContentMatchExactly Pester
diff --git a/Functions/Assertions/FileContentMatchMultiline.Tests.ps1 b/Functions/Assertions/FileContentMatchMultiline.Tests.ps1
index 5467ee3c0..373ebcaec 100644
--- a/Functions/Assertions/FileContentMatchMultiline.Tests.ps1
+++ b/Functions/Assertions/FileContentMatchMultiline.Tests.ps1
@@ -3,13 +3,13 @@ Set-StrictMode -Version Latest
InModuleScope Pester {
Describe "PesterFileContentMatchMultiline" {
Context "when testing file contents" {
- Setup -File "test.txt" "this is line 1`nthis is line 2`nPester is awesome"
+ Setup -File "test.txt" "this is line 1$([System.Environment]::NewLine)this is line 2$([System.Environment]::NewLine)Pester is awesome"
It "returns true if the file matches the specified content on one line" {
"$TestDrive\test.txt" | Should FileContentMatchMultiline "Pester"
}
It "returns true if the file matches the specified content across multiple lines" {
- "$TestDrive\test.txt" | Should FileContentMatchMultiline "line 2`nPester"
+ "$TestDrive\test.txt" | Should FileContentMatchMultiline "line 2$([System.Environment]::NewLine)Pester"
}
It "returns false if the file does not contain the specified content" {
diff --git a/Functions/Assertions/PesterThrow.Tests.ps1 b/Functions/Assertions/PesterThrow.Tests.ps1
index ed1168acf..81416a6af 100644
--- a/Functions/Assertions/PesterThrow.Tests.ps1
+++ b/Functions/Assertions/PesterThrow.Tests.ps1
@@ -211,8 +211,8 @@ InModuleScope Pester {
PesterThrow { & $testScriptPath } $expectedErrorMessage > $null
$result = PesterThrowFailureMessage $unexpectedErrorMessage $expectedErrorMessage
- $result | Should Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage}, an exception was raised, message was {$unexpectedErrorMessage}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
- $result | Should -Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage}, an exception was raised, message was {$unexpectedErrorMessage}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result | Should Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage}, an exception was raised, message was {$unexpectedErrorMessage}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result | Should -Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage}, an exception was raised, message was {$unexpectedErrorMessage}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
}
It 'returns true if the actual message is the same as the expected message' {
@@ -237,8 +237,8 @@ InModuleScope Pester {
PesterThrow { & $testScriptPath } -ErrorId $expectedErrorId > $null
$result = PesterThrowFailureMessage $null -ExpectedErrorId $expectedErrorId
- $result | Should Match "^Expected: the expression to throw an exception with error id {$expectedErrorId}, an exception was raised, error id was {$unexpectedErrorId}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
- $result | Should -Match "^Expected: the expression to throw an exception with error id {$expectedErrorId}, an exception was raised, error id was {$unexpectedErrorId}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result | Should Match "^Expected: the expression to throw an exception with error id {$expectedErrorId}, an exception was raised, error id was {$unexpectedErrorId}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result | Should -Match "^Expected: the expression to throw an exception with error id {$expectedErrorId}, an exception was raised, error id was {$unexpectedErrorId}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
}
It 'returns true if the actual error id is the same as the expected error id' {
@@ -276,8 +276,8 @@ InModuleScope Pester {
PesterThrow { & $testScriptPath } $expectedErrorMessage > $null
$result = PesterThrowFailureMessage $null $expectedErrorMessage $expectedErrorId
- $result | Should Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$unexpectedErrorMessage} and error id was {$unexpectedErrorId}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
- $result | Should -Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$unexpectedErrorMessage} and error id was {$unexpectedErrorId}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result | Should Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$unexpectedErrorMessage} and error id was {$unexpectedErrorId}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result | Should -Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$unexpectedErrorMessage} and error id was {$unexpectedErrorId}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
}
It 'returns false if the actual message is not the same as the expected message when the actual error id and expected error id match' {
@@ -296,8 +296,8 @@ InModuleScope Pester {
PesterThrow { & $testScriptPath } $expectedErrorMessage > $null
$result = PesterThrowFailureMessage $null $expectedErrorMessage $expectedErrorId
- $result | Should Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$unexpectedErrorMessage} and error id was {$expectedErrorId}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
- $result | Should -Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$unexpectedErrorMessage} and error id was {$expectedErrorId}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result | Should Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$unexpectedErrorMessage} and error id was {$expectedErrorId}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result | Should -Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$unexpectedErrorMessage} and error id was {$expectedErrorId}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
}
It 'returns false if the actual error id is not the same as the expected error id when the actual message and expected message match' {
@@ -316,8 +316,8 @@ InModuleScope Pester {
PesterThrow { & $testScriptPath } $expectedErrorMessage > $null
$result = PesterThrowFailureMessage $null $expectedErrorMessage $expectedErrorId
- $result | Should Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$expectedErrorMessage} and error id was {$unexpectedErrorId}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
- $result | Should -Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$expectedErrorMessage} and error id was {$unexpectedErrorId}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result | Should Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$expectedErrorMessage} and error id was {$unexpectedErrorId}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result | Should -Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$expectedErrorMessage} and error id was {$unexpectedErrorId}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
}
}
@@ -331,15 +331,15 @@ InModuleScope Pester {
Set-Content -Path $testScriptPath -Value "throw '$unexpectedErrorMessage'"
$result = PesterThrow { & $testScriptPath } $expectedErrorMessage
- $result.FailureMessage | Should Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage}, an exception was raised, message was {$unexpectedErrorMessage}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
- $result.FailureMessage | Should -Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage}, an exception was raised, message was {$unexpectedErrorMessage}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result.FailureMessage | Should Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage}, an exception was raised, message was {$unexpectedErrorMessage}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result.FailureMessage | Should -Match "^Expected: the expression to throw an exception with message {$expectedErrorMessage}, an exception was raised, message was {$unexpectedErrorMessage}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
}
It 'returns true if the actual message is the same as the expected message' {
Set-Content -Path $testScriptPath -Value "throw 'error message'"
$result = PesterThrow { & $testScriptPath } -Negate
- $result.FailureMessage | Should Match "^Expected: the expression not to throw an exception. Message was {error message}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
- $result.FailureMessage | Should -Match "^Expected: the expression not to throw an exception. Message was {error message}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result.FailureMessage | Should Match "^Expected: the expression not to throw an exception. Message was {error message}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result.FailureMessage | Should -Match "^Expected: the expression not to throw an exception. Message was {error message}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
}
It 'returns false if the actual error id is the same as the expected error id' {
@@ -355,8 +355,8 @@ InModuleScope Pester {
"
$result = PesterThrow { & $testScriptPath } -ErrorId $expectedErrorId -Negate
- $result.FailureMessage | Should Match "^Expected: the expression not to throw an exception with error id {$expectedErrorId}, an exception was raised, error id was {$expectedErrorId}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
- $result.FailureMessage | Should -Match "^Expected: the expression not to throw an exception with error id {$expectedErrorId}, an exception was raised, error id was {$expectedErrorId}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result.FailureMessage | Should Match "^Expected: the expression not to throw an exception with error id {$expectedErrorId}, an exception was raised, error id was {$expectedErrorId}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result.FailureMessage | Should -Match "^Expected: the expression not to throw an exception with error id {$expectedErrorId}, an exception was raised, error id was {$expectedErrorId}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
}
It 'returns false if the actual message or actual error id is the same as the expected message or expected error id' {
@@ -373,8 +373,8 @@ InModuleScope Pester {
"
$result = PesterThrow { & $testScriptPath } $expectedErrorMessage -ErrorId $expectedErrorId -Negate
- $result.FailureMessage | Should Match "^Expected: the expression not to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$expectedErrorMessage} and error id was {$expectedErrorId}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
- $result.FailureMessage | Should -Match "^Expected: the expression not to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$expectedErrorMessage} and error id was {$expectedErrorId}`n from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result.FailureMessage | Should Match "^Expected: the expression not to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$expectedErrorMessage} and error id was {$expectedErrorId}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
+ $result.FailureMessage | Should -Match "^Expected: the expression not to throw an exception with message {$expectedErrorMessage} and error id {$expectedErrorId}, an exception was raised, message was {$expectedErrorMessage} and error id was {$expectedErrorId}$([System.Environment]::NewLine) from $([RegEx]::Escape($testScriptPath)):\d+ char:\d+"
}
}
}
diff --git a/Functions/Assertions/PesterThrow.ps1 b/Functions/Assertions/PesterThrow.ps1
index 0eef273f2..83a658937 100644
--- a/Functions/Assertions/PesterThrow.ps1
+++ b/Functions/Assertions/PesterThrow.ps1
@@ -79,11 +79,11 @@ function PesterThrowFailureMessage($ActualValue, $ExpectedMessage, $ExpectedErro
{ $ExpectedMessage } { 'message was {{{0}}}' -f $ActualExceptionMessage }
{ $ExpectedErrorId } { 'error id was {{{0}}}' -f $ActualErrorId }
}
- $null = $StringBuilder.Append(("{0}, an exception was {1}raised, {2}`n {3}" -f
+ $null = $StringBuilder.Append(("{0}, an exception was {1}raised, {2}$([System.Environment]::NewLine) {3}" -f
($Expected -join ' and '),
@{$true="";$false="not "}[$ActualExceptionWasThrown],
($Actual -join ' and '),
- ($ActualExceptionLine -replace "`n","`n ")
+ ($ActualExceptionLine -replace "`n","$([System.Environment]::NewLine) ")
))
}
@@ -107,16 +107,16 @@ function NotPesterThrowFailureMessage($ActualValue, $ExpectedMessage, $ExpectedE
{ $ExpectedMessage } { 'message was {{{0}}}' -f $ActualExceptionMessage }
{ $ExpectedErrorId } { 'error id was {{{0}}}' -f $ActualErrorId }
}
- $null = $StringBuilder.Append(("{0}, an exception was {1}raised, {2}`n {3}" -f
+ $null = $StringBuilder.Append(("{0}, an exception was {1}raised, {2}$([System.Environment]::NewLine) {3}" -f
($Expected -join ' and '),
(@{$true="";$false="not "}[$ActualExceptionWasThrown]),
($Actual -join ' and '),
- ($ActualExceptionLine -replace "`n","`n ")
+ ($ActualExceptionLine -replace "$([System.Environment]::NewLine)","$([System.Environment]::NewLine) ")
))
}
else
{
- $null = $StringBuilder.Append((". Message was {{{0}}}`n {1}" -f $ActualExceptionMessage, ($ActualExceptionLine -replace "`n","`n ")))
+ $null = $StringBuilder.Append((". Message was {{{0}}}$([System.Environment]::NewLine) {1}" -f $ActualExceptionMessage, ($ActualExceptionLine -replace "$([System.Environment]::NewLine)","$([System.Environment]::NewLine) ")))
}
return $StringBuilder.ToString()
diff --git a/Functions/Assertions/Set-TestInconclusive.ps1 b/Functions/Assertions/Set-TestInconclusive.ps1
index a6ab8cfa1..8f0c4d3df 100644
--- a/Functions/Assertions/Set-TestInconclusive.ps1
+++ b/Functions/Assertions/Set-TestInconclusive.ps1
@@ -57,7 +57,7 @@ function Set-TestInconclusive {
)
Assert-DescribeInProgress -CommandName Set-TestInconclusive
- $lineText = $MyInvocation.Line.TrimEnd("`n")
+ $lineText = $MyInvocation.Line.TrimEnd($([System.Environment]::NewLine))
$line = $MyInvocation.ScriptLineNumber
$file = $MyInvocation.ScriptName
diff --git a/Functions/Assertions/Should.ps1 b/Functions/Assertions/Should.ps1
index c3982c2ac..f2ecf3275 100644
--- a/Functions/Assertions/Should.ps1
+++ b/Functions/Assertions/Should.ps1
@@ -119,7 +119,7 @@ function Should {
end
{
$lineNumber = $MyInvocation.ScriptLineNumber
- $lineText = $MyInvocation.Line.TrimEnd("`n")
+ $lineText = $MyInvocation.Line.TrimEnd("$([System.Environment]::NewLine)")
$file = $MyInvocation.ScriptName
if ($PSCmdlet.ParameterSetName -eq 'Legacy')
diff --git a/Functions/Coverage.Tests.ps1 b/Functions/Coverage.Tests.ps1
index a0a0d029b..4f9a665b2 100644
--- a/Functions/Coverage.Tests.ps1
+++ b/Functions/Coverage.Tests.ps1
@@ -1,12 +1,14 @@
+Set-StrictMode -Version Latest
+
if ($PSVersionTable.PSVersion.Major -le 2) { return }
InModuleScope Pester {
Describe 'Code Coverage Analysis' {
$root = (Get-PSDrive TestDrive).Root
- $null = New-Item -Path $root\TestScript.ps1 -ItemType File -ErrorAction SilentlyContinue
+ $null = New-Item -Path $(Join-Path -Path $root -ChildPath TestScript.ps1) -ItemType File -ErrorAction SilentlyContinue
- Set-Content -Path $root\TestScript.ps1 -Value @'
+ Set-Content -Path $(Join-Path -Path $root -ChildPath TestScript.ps1) -Value @'
function FunctionOne
{
function NestedFunction
@@ -35,13 +37,13 @@ InModuleScope Pester {
$testState = New-PesterState -Path $root
# Path deliberately duplicated to make sure the code doesn't produce multiple breakpoints for the same commands
- Enter-CoverageAnalysis -CodeCoverage "$root\TestScript.ps1", "$root\TestScript.ps1" -PesterState $testState
+ Enter-CoverageAnalysis -CodeCoverage "$(Join-Path -Path $root -ChildPath TestScript.ps1)", "$(Join-Path -Path $root -ChildPath TestScript.ps1)" -PesterState $testState
It 'Has the proper number of breakpoints defined' {
$testState.CommandCoverage.Count | Should Be 7
}
- $null = & "$root\TestScript.ps1"
+ $null = & "$(Join-Path -Path $root -ChildPath TestScript.ps1)"
$coverageReport = Get-CoverageReport -PesterState $testState
It 'Reports the proper number of executed commands' {
@@ -77,7 +79,7 @@ InModuleScope Pester {
$jaCoCoReportXml = $jaCoCoReportXml -replace 'Pester \([^\)]*','Pester (date'
$jaCoCoReportXml = $jaCoCoReportXml -replace 'start="[0-9]*"','start=""'
$jaCoCoReportXml = $jaCoCoReportXml -replace 'dump="[0-9]*"','dump=""'
- $jaCoCoReportXml = $jaCoCoReportXml -replace '\n',''
+ $jaCoCoReportXml = $jaCoCoReportXml -replace "$([System.Environment]::NewLine)",''
$jaCoCoReportXml | should be ''
}
Exit-CoverageAnalysis -PesterState $testState
@@ -86,13 +88,13 @@ InModuleScope Pester {
Context 'Single function with missed commands' {
$testState = New-PesterState -Path $root
- Enter-CoverageAnalysis -CodeCoverage @{Path = "$root\TestScript.ps1"; Function = 'FunctionTwo'} -PesterState $testState
+ Enter-CoverageAnalysis -CodeCoverage @{Path = "$(Join-Path -Path $root -ChildPath TestScript.ps1)"; Function = 'FunctionTwo'} -PesterState $testState
It 'Has the proper number of breakpoints defined' {
$testState.CommandCoverage.Count | Should Be 1
}
- $null = & "$root\TestScript.ps1"
+ $null = & "$(Join-Path -Path $root -ChildPath TestScript.ps1)"
$coverageReport = Get-CoverageReport -PesterState $testState
It 'Reports the proper number of executed commands' {
@@ -121,13 +123,13 @@ InModuleScope Pester {
Context 'Single function with no missed commands' {
$testState = New-PesterState -Path $root
- Enter-CoverageAnalysis -CodeCoverage @{Path = "$root\TestScript.ps1"; Function = 'FunctionOne'} -PesterState $testState
+ Enter-CoverageAnalysis -CodeCoverage @{Path = "$(Join-Path -Path $root -ChildPath TestScript.ps1)"; Function = 'FunctionOne'} -PesterState $testState
It 'Has the proper number of breakpoints defined' {
$testState.CommandCoverage.Count | Should Be 5
}
- $null = & "$root\TestScript.ps1"
+ $null = & "$(Join-Path -Path $root -ChildPath TestScript.ps1)"
$coverageReport = Get-CoverageReport -PesterState $testState
It 'Reports the proper number of executed commands' {
@@ -156,13 +158,13 @@ InModuleScope Pester {
Context 'Range of lines' {
$testState = New-PesterState -Path $root
- Enter-CoverageAnalysis -CodeCoverage @{Path = "$root\TestScript.ps1"; StartLine = 11; EndLine = 12 } -PesterState $testState
+ Enter-CoverageAnalysis -CodeCoverage @{Path = "$(Join-Path -Path $root -ChildPath TestScript.ps1)"; StartLine = 11; EndLine = 12 } -PesterState $testState
It 'Has the proper number of breakpoints defined' {
$testState.CommandCoverage.Count | Should Be 2
}
- $null = & "$root\TestScript.ps1"
+ $null = & "$(Join-Path -Path $root -ChildPath TestScript.ps1)"
$coverageReport = Get-CoverageReport -PesterState $testState
It 'Reports the proper number of executed commands' {
@@ -191,13 +193,13 @@ InModuleScope Pester {
Context 'Wildcard resolution' {
$testState = New-PesterState -Path $root
- Enter-CoverageAnalysis -CodeCoverage @{Path = "$root\*.ps1"; Function = '*' } -PesterState $testState
+ Enter-CoverageAnalysis -CodeCoverage @{Path = "$(Join-Path -Path $root -ChildPath *.ps1)"; Function = '*' } -PesterState $testState
It 'Has the proper number of breakpoints defined' {
$testState.CommandCoverage.Count | Should Be 6
}
- $null = & "$root\TestScript.ps1"
+ $null = & "$(Join-Path -Path $root -ChildPath TestScript.ps1)"
$coverageReport = Get-CoverageReport -PesterState $testState
It 'Reports the proper number of executed commands' {
@@ -233,14 +235,35 @@ InModuleScope Pester {
}
Describe 'Stripping common parent paths' {
- $paths = @(
- Normalize-Path 'C:\Common\Folder\UniqueSubfolder1/File.ps1'
- Normalize-Path 'C:\Common\Folder\UniqueSubfolder2/File2.ps1'
- Normalize-Path 'C:\Common\Folder\UniqueSubfolder3/File3.ps1'
- )
+
+ If ( (& $SafeCommands['Get-Variable'] -Name IsLinux -Scope Global -ErrorAction SilentlyContinue) -or
+ (& $SafeCommands['Get-Variable'] -Name IsMacOS -Scope Global -ErrorAction SilentlyContinue)) {
+
+ $paths = @(
+ Normalize-Path '/usr/lib/Common\Folder\UniqueSubfolder1/File.ps1'
+ Normalize-Path '/usr/lib/Common\Folder\UniqueSubfolder2/File2.ps1'
+ Normalize-Path '/usr/lib/Common\Folder\UniqueSubfolder3/File3.ps1'
+
+ $expectedCommonPath = Normalize-Path '/usr/lib/Common/Folder'
+
+ )
+
+ }
+ Else {
+
+ $paths = @(
+ Normalize-Path 'C:\Common\Folder\UniqueSubfolder1/File.ps1'
+ Normalize-Path 'C:\Common\Folder\UniqueSubfolder2/File2.ps1'
+ Normalize-Path 'C:\Common\Folder\UniqueSubfolder3/File3.ps1'
+
+ $expectedCommonPath = Normalize-Path 'C:\Common/Folder'
+
+ )
+
+ }
$commonPath = Get-CommonParentPath -Path $paths
- $expectedCommonPath = Normalize-Path 'C:\Common/Folder'
+
It 'Identifies the correct parent path' {
$commonPath | Should Be $expectedCommonPath
@@ -254,8 +277,9 @@ InModuleScope Pester {
}
}
- if ((Get-Module -ListAvailable PSDesiredStateConfiguration) -and $PSVersionTable.PSVersion.Major -ge 4)
- {
+ #Workaround for Linux and MacOS - they don't have DSC by default installed with PowerShell - disable tests on these platforms
+ if ((Get-Module -ListAvailable PSDesiredStateConfiguration) -and $PSVersionTable.PSVersion.Major -ge 4 -and ((GetPesterOS) -eq 'Windows')) {
+
Describe 'Analyzing coverage of a DSC configuration' {
$root = (Get-PSDrive TestDrive).Root
@@ -289,7 +313,6 @@ InModuleScope Pester {
$doesnotexecute = $true # Triggers breakpoint
'@
-
$testState = New-PesterState -Path $root
Enter-CoverageAnalysis -CodeCoverage "$root\TestScriptWithConfiguration.ps1" -PesterState $testState
diff --git a/Functions/Coverage.ps1 b/Functions/Coverage.ps1
index ff3e8ada3..2dc7c2371 100644
--- a/Functions/Coverage.ps1
+++ b/Functions/Coverage.ps1
@@ -589,16 +589,17 @@ function Get-JaCoCoReportXml {
}
$allCommands = $CoverageReport.MissedCommands + $CoverageReport.HitCommands
- [long]$totalFunctions = ($allCommands | ForEach-Object {$_.File+$_.Function} | Select-Object -uniq ).Count
- [long]$hitFunctions = ($CoverageReport.HitCommands | ForEach-Object {$_.File+$_.Function} | Select-Object -uniq ).Count
+ [long]$totalFunctions = ($allCommands | ForEach-Object {$_.File+$_.Function} | Select-Object -Unique ).Count
+ [long]$hitFunctions = ($CoverageReport.HitCommands | ForEach-Object {$_.File+$_.Function} | Select-Object -Unique ).Count
[long]$missedFunctions = $totalFunctions - $hitFunctions
- [long]$totalLines = ($allCommands | ForEach-Object {$_.File+$_.Line} | Select-Object -uniq ).Count
- [long]$hitLines = ($CoverageReport.HitCommands | ForEach-Object {$_.File+$_.Line} | Select-Object -uniq ).Count
+ [long]$totalLines = ($allCommands | ForEach-Object {$_.File+$_.Line} | Select-Object -Unique ).Count
+ [long]$hitLines = ($CoverageReport.HitCommands | ForEach-Object {$_.File+$_.Line} | Select-Object -Unique ).Count
[long]$missedLines = $totalLines - $hitLines
[long]$totalFiles = $CoverageReport.NumberOfFilesAnalyzed
- [long]$hitFiles = ($CoverageReport.HitCommands | ForEach-Object {$_.File} | Select-Object -uniq ).Count
+
+ [long]$hitFiles = $(Measure-Object -InputObject $($CoverageReport.HitCommands | ForEach-Object {$_.File} | Select-Object -Unique )).Count
[long]$missedFiles = $totalFiles - $hitFiles
$now = & $SafeCommands['Get-Date']
@@ -607,13 +608,13 @@ function Get-JaCoCoReportXml {
[long]$startTime = [math]::Floor($endTime - $PesterState.Time.TotalSeconds*1000)
# the JaCoCo xml format without the doctype, as the XML stuff does not like DTD's.
- $jaCoCoReport += "`n"
- $jaCoCoReport += "`n"
- $jaCoCoReport += "`n"
- $jaCoCoReport += "`n"
- $jaCoCoReport += "`n"
- $jaCoCoReport += "`n"
- $jaCoCoReport += "`n"
+ $jaCoCoReport = "$([System.Environment]::NewLine)"
+ $jaCoCoReport += "$([System.Environment]::NewLine)"
+ $jaCoCoReport += "$([System.Environment]::NewLine)"
+ $jaCoCoReport += "$([System.Environment]::NewLine)"
+ $jaCoCoReport += "$([System.Environment]::NewLine)"
+ $jaCoCoReport += "$([System.Environment]::NewLine)"
+ $jaCoCoReport += "$([System.Environment]::NewLine)"
$jaCoCoReport += ""
[xml] $jaCoCoReportXml = $jaCoCoReport
@@ -629,6 +630,6 @@ function Get-JaCoCoReportXml {
$jaCoCoReportXml.report.counter[3].missed = $missedFiles.ToString()
$jaCoCoReportXml.report.counter[3].covered = $hitFiles.ToString()
# There is no pretty way to insert the Doctype, as microsoft has deprecated the DTD stuff.
- $jaCoCoReportDocType = "`n"
+ $jaCoCoReportDocType = "$([System.Environment]::NewLine)"
return $jaCocoReportXml.OuterXml.Insert(54, $jaCoCoReportDocType)
}
diff --git a/Functions/Describe.ps1 b/Functions/Describe.ps1
index 629aca79f..92f34af7b 100644
--- a/Functions/Describe.ps1
+++ b/Functions/Describe.ps1
@@ -179,7 +179,7 @@ function DescribeImpl {
}
catch
{
- $firstStackTraceLine = $_.InvocationInfo.PositionMessage.Trim() -split '\r?\n' | & $SafeCommands['Select-Object'] -First 1
+ $firstStackTraceLine = $_.InvocationInfo.PositionMessage.Trim() -split "$([System.Environment]::NewLine)" | & $SafeCommands['Select-Object'] -First 1
$Pester.AddTestResult("Error occurred in $CommandUsed block", "Failed", $null, $_.Exception.Message, $firstStackTraceLine, $null, $null, $_)
if ($null -ne $TestOutputBlock)
{
diff --git a/Functions/Environment.Tests.ps1 b/Functions/Environment.Tests.ps1
index aa7bbb093..b6fa3629c 100644
--- a/Functions/Environment.Tests.ps1
+++ b/Functions/Environment.Tests.ps1
@@ -23,7 +23,7 @@ InModuleScope -ModuleName Pester {
Context "Windows with PowerShell 6 and higher" {
Mock Get-Variable -ParameterFilter { $Name -eq 'IsWindows' -and $ValueOnly } -MockWith { $true }
Mock Get-Variable -ParameterFilter { $Name -eq 'IsLinux' -and $ValueOnly } -MockWith { $false }
- Mock Get-Variable -ParameterFilter { $Name -eq 'IsOSX' -and $ValueOnly } -MockWith { $false }
+ Mock Get-Variable -ParameterFilter { $Name -eq 'IsMacOS' -and $ValueOnly } -MockWith { $false }
Mock GetPesterPsVersion { 6 }
$os = GetPesterOs
@@ -43,7 +43,7 @@ InModuleScope -ModuleName Pester {
Context "Linux with PowerShell 6 and higher" {
Mock Get-Variable -ParameterFilter { $Name -eq 'IsWindows' -and $ValueOnly } -MockWith { $false }
Mock Get-Variable -ParameterFilter { $Name -eq 'IsLinux' -and $ValueOnly } -MockWith { $true }
- Mock Get-Variable -ParameterFilter { $Name -eq 'IsOSX' -and $ValueOnly } -MockWith { $false }
+ Mock Get-Variable -ParameterFilter { $Name -eq 'IsMacOS' -and $ValueOnly } -MockWith { $false }
Mock GetPesterPsVersion { 6 }
$os = GetPesterOs
@@ -56,19 +56,19 @@ InModuleScope -ModuleName Pester {
}
}
- Context "OSx with PowerShell 6 and higher" {
+ Context "macOS with PowerShell 6 and higher" {
Mock Get-Variable -ParameterFilter { $Name -eq 'IsWindows' -and $ValueOnly } -MockWith { $false }
Mock Get-Variable -ParameterFilter { $Name -eq 'IsLinux' -and $ValueOnly } -MockWith { $false }
- Mock Get-Variable -ParameterFilter { $Name -eq 'IsOSX' -and $ValueOnly } -MockWith { $true }
+ Mock Get-Variable -ParameterFilter { $Name -eq 'IsMacOS' -and $ValueOnly } -MockWith { $true }
Mock GetPesterPsVersion { 6 }
$os = GetPesterOs
- It "Returns 'OSX' when `$IsOSX is `$true and powershell version is 6 or higher" {
- $os | Should -Be 'OSX'
+ It "Returns 'OSX' when `$IsMacOS is `$true and powershell version is 6 or higher" {
+ $os | Should -Be 'macOS'
}
- It "Uses Get-Variable to retreive IsOSX" {
- Assert-MockCalled Get-Variable -ParameterFilter { $Name -eq 'IsOSX' -and $ValueOnly } -Exactly 1
+ It "Uses Get-Variable to retreive IsMacOS" {
+ Assert-MockCalled Get-Variable -ParameterFilter { $Name -eq 'IsMacOS' -and $ValueOnly } -Exactly 1
}
}
}
diff --git a/Functions/Environment.ps1 b/Functions/Environment.ps1
index 0f3754f41..786b996f8 100644
--- a/Functions/Environment.ps1
+++ b/Functions/Environment.ps1
@@ -15,9 +15,9 @@ function GetPesterOs
{
'Windows'
}
- elseif (Get-Variable -Name 'IsOSX' -ErrorAction 'SilentlyContinue' -ValueOnly )
+ elseif (Get-Variable -Name 'IsMacOS' -ErrorAction 'SilentlyContinue' -ValueOnly )
{
- 'OSX'
+ 'macOS'
}
elseif (Get-Variable -Name 'IsLinux' -ErrorAction 'SilentlyContinue' -ValueOnly )
{
diff --git a/Functions/Gherkin.Tests.ps1 b/Functions/Gherkin.Tests.ps1
index 918871433..0c68526b9 100644
--- a/Functions/Gherkin.Tests.ps1
+++ b/Functions/Gherkin.Tests.ps1
@@ -1,6 +1,7 @@
-if ($PSVersionTable.PSVersion.Major -le 2) { return }
-
Set-StrictMode -Version Latest
+
+If (($PSVersionTable.ContainsKey('PSEdition')) -and ($PSVersionTable.PSEdition -eq 'Core') -or ($PSVersionTable.PSVersion.Major -le 2)) { return }
+
$scriptRoot = Split-Path (Split-Path $MyInvocation.MyCommand.Path)
# Calling this in a job so we don't monkey with the active pester state that's already running
diff --git a/Functions/Gherkin.ps1 b/Functions/Gherkin.ps1
index 81722d261..8b5c1b8a7 100644
--- a/Functions/Gherkin.ps1
+++ b/Functions/Gherkin.ps1
@@ -1,5 +1,10 @@
-# Work around bug in PowerShell 2 type loading...
-Microsoft.PowerShell.Core\Import-Module -Name "${Script:PesterRoot}\lib\Gherkin.dll"
+If (($PSVersionTable.ContainsKey('PSEdition')) -and ($PSVersionTable.PSEdition -eq 'Core') -or ($PSVersionTable.PSVersion.Major -le 2)) {
+ return
+}
+Else {
+ # Work around bug in PowerShell 2 type loading...
+ Microsoft.PowerShell.Core\Import-Module -Name "${Script:PesterRoot}\lib\Gherkin.dll"
+}
$GherkinSteps = @{}
$GherkinHooks = @{
diff --git a/Functions/GherkinHook.Tests.ps1 b/Functions/GherkinHook.Tests.ps1
index 123257782..d714e257a 100644
--- a/Functions/GherkinHook.Tests.ps1
+++ b/Functions/GherkinHook.Tests.ps1
@@ -1,7 +1,7 @@
-if ($PSVersionTable.PSVersion.Major -le 2) { return }
-
Set-StrictMode -Version Latest
+If (($PSVersionTable.ContainsKey('PSEdition')) -and ($PSVersionTable.PSEdition -eq 'Core') -or ($PSVersionTable.PSVersion.Major -le 2)) { return }
+
Describe 'Testing Gerkin Hook' {
It 'Generates a function named "BeforeEachFeature" with mandatory Tags and Script parameters' {
$command = &(Get-Module Pester) { Get-Command BeforeEachFeature -Module Pester }
diff --git a/Functions/GherkinStep.Tests.ps1 b/Functions/GherkinStep.Tests.ps1
index 32a003378..09133d9ab 100644
--- a/Functions/GherkinStep.Tests.ps1
+++ b/Functions/GherkinStep.Tests.ps1
@@ -1,7 +1,7 @@
-if ($PSVersionTable.PSVersion.Major -le 2) { return }
-
Set-StrictMode -Version Latest
+If (($PSVersionTable.ContainsKey('PSEdition')) -and ($PSVersionTable.PSEdition -eq 'Core') -or ($PSVersionTable.PSVersion.Major -le 2)) { return }
+
Describe 'Testing Gerkin Step' {
It 'Generates a function named "GherkinStep" with mandatory name and test parameters' {
$command = &(Get-Module Pester) { Get-Command GherkinStep -Module Pester }
diff --git a/Functions/It.ps1 b/Functions/It.ps1
index 9de7d51d4..aa501b375 100644
--- a/Functions/It.ps1
+++ b/Functions/It.ps1
@@ -280,7 +280,7 @@ function Invoke-Test
$pester.LeaveTest()
}
- $result = ConvertTo-PesterResult -ErrorRecord $errorRecord
+ $result = ConvertTo-PesterResult -Name $Name -ErrorRecord $errorRecord
$orderedParameters = Get-OrderedParameterDictionary -ScriptBlock $ScriptBlock -Dictionary $Parameters
$Pester.AddTestResult( $result.name, $result.Result, $null, $result.FailureMessage, $result.StackTrace, $ParameterizedSuiteName, $orderedParameters, $result.ErrorRecord )
& $SafeCommands['Write-Progress'] -Activity "Running test '$Name'" -Completed -Status Processing
diff --git a/Functions/Mock.Tests.ps1 b/Functions/Mock.Tests.ps1
index b5695118c..382385933 100644
--- a/Functions/Mock.Tests.ps1
+++ b/Functions/Mock.Tests.ps1
@@ -105,6 +105,9 @@ Describe "When calling Mock on existing cmdlet" {
}
Describe 'When calling Mock on an alias' {
+
+ (Get-Item Env:PATH).Value
+
$originalPath = $env:path
try
@@ -227,13 +230,30 @@ Describe 'When calling Mock on an external script' {
Remove-Item $ps1File -Force -ErrorAction SilentlyContinue
}
-Describe 'When calling Mock on an application command' {
- Mock schtasks.exe {return 'I am not schtasks.exe'}
+InModuleScope -ModuleName Pester {
+ Describe 'When calling Mock on an application command' {
- $result = schtasks.exe
+ If ((GetPesterOs) -ne 'Windows') {
- It 'Should Invoke the mocked script' {
- $result | Should Be 'I am not schtasks.exe'
+ Mock visudo {return 'I am not visudo'}
+
+ $result = visudo
+
+ It 'Should Invoke the mocked script' {
+ $result | Should Be 'I am not visudo'
+ }
+
+ }
+ Else {
+
+ Mock schtasks.exe {return 'I am not schtasks.exe'}
+
+ $result = schtasks.exe
+
+ It 'Should Invoke the mocked script' {
+ $result | Should Be 'I am not schtasks.exe'
+ }
+ }
}
}
@@ -581,7 +601,7 @@ Describe "When Creating a Verifiable Mock that is not called" {
}
It "Should throw" {
- $result.Exception.Message | Should Be "`r`n Expected FunctionUnderTest to be called with `$param1 -eq `"one`""
+ $result.Exception.Message | Should Be "$([System.Environment]::NewLine) Expected FunctionUnderTest to be called with `$param1 -eq `"one`""
}
}
@@ -600,7 +620,7 @@ Describe "When Creating a Verifiable Mock that is not called" {
}
It "Should throw" {
- $result.Exception.Message | Should Be "`r`n Expected ModuleFunctionUnderTest in module TestModule to be called with `$param1 -eq `"one`""
+ $result.Exception.Message | Should Be "$([System.Environment]::NewLine) Expected ModuleFunctionUnderTest in module TestModule to be called with `$param1 -eq `"one`""
}
AfterAll {
@@ -851,14 +871,34 @@ Describe 'Dot Source Test' {
}
}
-Describe 'Mocking Cmdlets with dynamic parameters' {
- $mockWith = { if (-not $CodeSigningCert) { throw 'CodeSigningCert variable not found, or set to false!' } }
- Mock Get-ChildItem -MockWith $mockWith -ParameterFilter { [bool]$CodeSigningCert }
+InModuleScope -ModuleName Pester {
+
+ Describe 'Mocking Cmdlets with dynamic parameters' {
+
+ If ((GetPesterOs) -ne 'Windows') {
+
+ $mockWith = { if (-not $Hidden) { throw 'Hidden variable not found, or set to false!' } }
+ Mock Get-ChildItem -MockWith $mockWith -ParameterFilter { [bool]$Hidden }
+
+ It 'Allows calls to be made with dynamic parameters (including parameter filters)' {
+ { Get-ChildItem -Path / -Hidden } | Should Not Throw
+ Assert-MockCalled Get-ChildItem
+ }
+
+ }
+ Else {
+
+ $mockWith = { if (-not $CodeSigningCert) { throw 'CodeSigningCert variable not found, or set to false!' } }
+ Mock Get-ChildItem -MockWith $mockWith -ParameterFilter { [bool]$CodeSigningCert }
+
+ It 'Allows calls to be made with dynamic parameters (including parameter filters)' {
+ { Get-ChildItem -Path Cert:\ -CodeSigningCert } | Should Not Throw
+ Assert-MockCalled Get-ChildItem
+ }
+ }
- It 'Allows calls to be made with dynamic parameters (including parameter filters)' {
- { Get-ChildItem -Path Cert:\ -CodeSigningCert } | Should Not Throw
- Assert-MockCalled Get-ChildItem
}
+
}
Describe 'Mocking functions with dynamic parameters' {
@@ -1200,91 +1240,162 @@ Describe 'Mocking functions with dynamic parameters' {
}
}
-Describe 'Mocking Cmdlets with dynamic parameters in a module' {
- New-Module -Name TestModule {
- function PublicFunction { Get-ChildItem -Path Cert:\ -CodeSigningCert }
- } | Import-Module -Force
+InModuleScope -ModuleName Pester {
- $mockWith = { if (-not $CodeSigningCert) { throw 'CodeSigningCert variable not found, or set to false!' } }
- Mock Get-ChildItem -MockWith $mockWith -ModuleName TestModule -ParameterFilter { [bool]$CodeSigningCert }
+ Describe 'Mocking Cmdlets with dynamic parameters in a module' {
- It 'Allows calls to be made with dynamic parameters (including parameter filters)' {
- { TestModule\PublicFunction } | Should Not Throw
- Assert-MockCalled Get-ChildItem -ModuleName TestModule
- }
+ If ((GetPesterOs) -ne 'Windows') {
- AfterAll {
- Remove-Module TestModule -Force
+ New-Module -Name TestModule {
+ function PublicFunction { Get-ChildItem -Path \ -Hidden }
+ } | Import-Module -Force
+
+ $mockWith = { if (-not $Hidden) { throw 'Hidden variable not found, or set to false!' } }
+ Mock Get-ChildItem -MockWith $mockWith -ModuleName TestModule -ParameterFilter { [bool]$Hidden }
+
+ }
+ Else {
+
+ New-Module -Name TestModule {
+ function PublicFunction { Get-ChildItem -Path Cert:\ -CodeSigningCert }
+ } | Import-Module -Force
+
+ $mockWith = { if (-not $CodeSigningCert) { throw 'CodeSigningCert variable not found, or set to false!' } }
+ Mock Get-ChildItem -MockWith $mockWith -ModuleName TestModule -ParameterFilter { [bool]$CodeSigningCert }
+
+ }
+
+ It 'Allows calls to be made with dynamic parameters (including parameter filters)' {
+ { TestModule\PublicFunction } | Should Not Throw
+ Assert-MockCalled Get-ChildItem -ModuleName TestModule
+ }
+
+ AfterAll {
+ Remove-Module TestModule -Force
+ }
}
-}
-Describe 'DynamicParam blocks in other scopes' {
- New-Module -Name TestModule1 {
- $script:DoDynamicParam = $true
+ Describe 'DynamicParam blocks in other scopes' {
- function DynamicParamFunction {
- [CmdletBinding()]
- param ( )
+ If ((GetPesterOs) -ne 'Windows') {
- DynamicParam {
- if ($script:DoDynamicParam)
- {
- if ($PSVersionTable.PSVersion.Major -ge 3)
- {
- # -Parameters needs to be a PSBoundParametersDictionary object to work properly, due to internal
- # details of the PS engine in v5. Naturally, this is an internal type and we need to use reflection
- # to make a new one.
+ New-Module -Name TestModule1 {
+ $script:DoDynamicParam = $true
+
+ function DynamicParamFunction {
+ [CmdletBinding()]
+ param ( )
- $flags = [System.Reflection.BindingFlags]'Instance,NonPublic'
- $params = $PSBoundParameters.GetType().GetConstructor($flags, $null, @(), $null).Invoke(@())
+ DynamicParam {
+ if ($script:DoDynamicParam)
+ {
+
+ $flags = [System.Reflection.BindingFlags]'Instance,NonPublic'
+ $params = $PSBoundParameters.GetType().GetConstructor($flags, $null, @(), $null).Invoke(@())
+
+ $params['Path'] = [string[]]'/'
+ Get-MockDynamicParameter -CmdletName Get-ChildItem -Parameters $params
+ }
}
- else
+
+ end
{
- $params = @{}
+ 'I am the original function'
}
+ }
+ } | Import-Module -Force
- $params['Path'] = [string[]]'Cert:\'
- Get-MockDynamicParameter -CmdletName Get-ChildItem -Parameters $params
+ New-Module -Name TestModule2 {
+ function CallingFunction
+ {
+ DynamicParamFunction -Hidden
}
- }
- end
- {
- 'I am the original function'
- }
- }
- } | Import-Module -Force
+ function CallingFunction2 {
+ [CmdletBinding()]
+ param (
+ [ValidateScript({ [bool](DynamicParamFunction -Hidden) })]
+ [string]
+ $Whatever
+ )
+ }
+ } | Import-Module -Force
+
+ Mock DynamicParamFunction { if ($Hidden) { 'I am the mocked function' } } -ModuleName TestModule2
- New-Module -Name TestModule2 {
- function CallingFunction
- {
- DynamicParamFunction -CodeSigningCert
}
+ Else {
+
+ New-Module -Name TestModule1 {
+ $script:DoDynamicParam = $true
+
+ function DynamicParamFunction {
+ [CmdletBinding()]
+ param ( )
+
+ DynamicParam {
+ if ($script:DoDynamicParam)
+ {
+ if ($PSVersionTable.PSVersion.Major -ge 3)
+ {
+ # -Parameters needs to be a PSBoundParametersDictionary object to work properly, due to internal
+ # details of the PS engine in v5. Naturally, this is an internal type and we need to use reflection
+ # to make a new one.
+
+ $flags = [System.Reflection.BindingFlags]'Instance,NonPublic'
+ $params = $PSBoundParameters.GetType().GetConstructor($flags, $null, @(), $null).Invoke(@())
+ }
+ else
+ {
+ $params = @{}
+ }
+
+ $params['Path'] = [string[]]'Cert:\'
+ Get-MockDynamicParameter -CmdletName Get-ChildItem -Parameters $params
+ }
+ }
+
+ end
+ {
+ 'I am the original function'
+ }
+ }
+ } | Import-Module -Force
+
+ New-Module -Name TestModule2 {
+ function CallingFunction
+ {
+ DynamicParamFunction -CodeSigningCert
+ }
+
+ function CallingFunction2 {
+ [CmdletBinding()]
+ param (
+ [ValidateScript({ [bool](DynamicParamFunction -CodeSigningCert) })]
+ [string]
+ $Whatever
+ )
+ }
+ } | Import-Module -Force
+
+ Mock DynamicParamFunction { if ($CodeSigningCert) { 'I am the mocked function' } } -ModuleName TestModule2
- function CallingFunction2 {
- [CmdletBinding()]
- param (
- [ValidateScript({ [bool](DynamicParamFunction -CodeSigningCert) })]
- [string]
- $Whatever
- )
}
- } | Import-Module -Force
- Mock DynamicParamFunction { if ($CodeSigningCert) { 'I am the mocked function' } } -ModuleName TestModule2
+ It 'Properly evaluates dynamic parameters when called from another scope' {
+ CallingFunction | Should Be 'I am the mocked function'
+ }
- It 'Properly evaluates dynamic parameters when called from another scope' {
- CallingFunction | Should Be 'I am the mocked function'
- }
+ It 'Properly evaluates dynamic parameters when called from another scope when the call is from a ValidateScript block' {
+ CallingFunction2 -Whatever 'Whatever'
+ }
- It 'Properly evaluates dynamic parameters when called from another scope when the call is from a ValidateScript block' {
- CallingFunction2 -Whatever 'Whatever'
+ AfterAll {
+ Remove-Module TestModule1 -Force
+ Remove-Module TestModule2 -Force
+ }
}
- AfterAll {
- Remove-Module TestModule1 -Force
- Remove-Module TestModule2 -Force
- }
}
Describe 'Parameter Filters and Common Parameters' {
diff --git a/Functions/Mock.ps1 b/Functions/Mock.ps1
index 45a2cf665..3664402d7 100644
--- a/Functions/Mock.ps1
+++ b/Functions/Mock.ps1
@@ -422,7 +422,7 @@ This will not throw an exception because the mock was invoked.
$function = $array[1]
$module = $array[0]
- $message = "`r`n Expected $function "
+ $message = "$([System.Environment]::NewLine) Expected $function "
if ($module) { $message += "in module $module " }
$message += "to be called with $($unVerified[$mock].Filter)"
}
@@ -660,7 +660,7 @@ param(
}
}
- $lineText = $MyInvocation.Line.TrimEnd("`n")
+ $lineText = $MyInvocation.Line.TrimEnd("$([System.Environment]::NewLine)")
$line = $MyInvocation.ScriptLineNumber
if($matchingCalls.Count -ne $times -and ($Exactly -or ($times -eq 0)))
@@ -1294,13 +1294,16 @@ function Get-DynamicParamBlock
}
else
{
- if ($null -ne $ScriptBlock.Ast.Body.DynamicParamBlock)
+ If ( $ScriptBlock.AST.psobject.Properties.Name -match "Body")
{
- $statements = $ScriptBlock.Ast.Body.DynamicParamBlock.Statements |
- & $SafeCommands['Select-Object'] -ExpandProperty Extent |
- & $SafeCommands['Select-Object'] -ExpandProperty Text
+ if ($null -ne $ScriptBlock.Ast.Body.DynamicParamBlock)
+ {
+ $statements = $ScriptBlock.Ast.Body.DynamicParamBlock.Statements |
+ & $SafeCommands['Select-Object'] -ExpandProperty Extent |
+ & $SafeCommands['Select-Object'] -ExpandProperty Text
- return $statements -join "`r`n"
+ return $statements -join "$([System.Environment]::NewLine)"
+ }
}
}
}
@@ -1381,7 +1384,7 @@ function Get-DynamicParametersForCmdlet
return
}
- if ($PSVersionTable.PSVersion -ge '5.0.10586.122')
+ if ('5.0.10586.122' -lt $PSVersionTable.PSVersion)
{
# Older version of PS required Reflection to do this. It has run into problems on occasion with certain cmdlets,
# such as ActiveDirectory and AzureRM, so we'll take advantage of the newer PSv5 engine features if at all possible.
diff --git a/Functions/New-Fixture.ps1 b/Functions/New-Fixture.ps1
index 067555b12..b646ab963 100644
--- a/Functions/New-Fixture.ps1
+++ b/Functions/New-Fixture.ps1
@@ -67,7 +67,7 @@ function New-Fixture {
)
#region File contents
#keep this formatted as is. the format is output to the file as is, including indentation
- $scriptCode = "function $name {`r`n`r`n}"
+ $scriptCode = "function $name {$([System.Environment]::NewLine)$([System.Environment]::NewLine)}"
$testCode = '$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace ''\.Tests\.'', ''.''
diff --git a/Functions/Output.Tests.ps1 b/Functions/Output.Tests.ps1
index 3e7b6fb1c..13f903ab5 100644
--- a/Functions/Output.Tests.ps1
+++ b/Functions/Output.Tests.ps1
@@ -66,7 +66,7 @@ Describe 'ConvertTo-PesterResult' {
#on which line the test failed.
$errorRecord = $null
try{'something' | should be 'nothing'}catch{ $errorRecord=$_} ; $script={}
- $result = & $getPesterResult 0 $errorRecord
+ $result = & $getPesterResult -Time 0 -ErrorRecord $errorRecord
It 'records the correct stack line number' {
$result.Stacktrace | should match "${thisScriptRegex}: line $($script.startPosition.StartLine)"
}
@@ -83,7 +83,7 @@ Describe 'ConvertTo-PesterResult' {
$errorRecord = $null
try { $object.ThrowSomething() } catch { $errorRecord = $_ }
- $pesterResult = & $getPesterResult 0 $errorRecord
+ $pesterResult = & $getPesterResult -Time 0 -ErrorRecord $errorRecord
$pesterResult.FailureMessage | Should Be $errorRecord.Exception.Message
}
@@ -93,7 +93,7 @@ Describe 'ConvertTo-PesterResult' {
$testPath = Join-Path $TestDrive test.ps1
$escapedTestPath = [regex]::Escape($testPath)
- Set-Content -Path $testPath -Value "`r`n'One' | Should Be 'Two'"
+ Set-Content -Path $testPath -Value "$([System.Environment]::NewLine)'One' | Should Be 'Two'"
try
{
@@ -104,7 +104,7 @@ Describe 'ConvertTo-PesterResult' {
$errorRecord = $_
}
- $result = & $getPesterResult 0 $errorRecord
+ $result = & $getPesterResult -Time 0 -ErrorRecord $errorRecord
It 'records the correct stack line number' {
@@ -119,31 +119,67 @@ Describe 'ConvertTo-PesterResult' {
InModuleScope -ModuleName Pester -ScriptBlock {
Describe "Format-PesterPath" {
+
It "Writes path correctly when it is given `$null" {
Format-PesterPath -Path $null | Should -Be $null
}
- It "Writes path correctly when it is provided as string" {
- Format-PesterPath -Path "C:\path" | Should -Be "C:\path"
- }
+ If ( (GetPesterOS) -ne 'Windows') {
+
+ It "Writes path correctly when it is provided as string" {
+ Format-PesterPath -Path "/home/username/folder1" | Should -Be "/home/username/folder1"
+ }
+
+ It "Writes path correctly when it is provided as string[]" {
+ Format-PesterPath -Path @("/home/username/folder1", "/home/username/folder2") -Delimiter ', ' | Should -Be "/home/username/folder1, /home/username/folder2"
+ }
+
+ It "Writes path correctly when provided through hashtable" {
+ Format-PesterPath -Path @{ Path = "/home/username/folder1" } | Should -Be "/home/username/folder1"
+ }
+
+ It "Writes path correctly when provided through array of hashtable" {
+ Format-PesterPath -Path @{ Path = "/home/username/folder1" }, @{ Path = "/home/username/folder2" } -Delimiter ', ' | Should -Be "/home/username/folder1, /home/username/folder2"
+ }
- It "Writes path correctly when it is provided as string[]" {
- Format-PesterPath -Path @("C:\path1", "C:\path2") -Delimiter ', ' | Should -Be "C:\path1, C:\path2"
- }
- It "Writes path correctly when provided through hashtable" {
- Format-PesterPath -Path @{ Path = "C:\path" } | Should -Be "C:\path"
}
+ Else {
+
+ It "Writes path correctly when it is provided as string" {
+ Format-PesterPath -Path "C:\path" | Should -Be "C:\path"
+ }
+
+ It "Writes path correctly when it is provided as string[]" {
+ Format-PesterPath -Path @("C:\path1", "C:\path2") -Delimiter ', ' | Should -Be "C:\path1, C:\path2"
+ }
+
+ It "Writes path correctly when provided through hashtable" {
+ Format-PesterPath -Path @{ Path = "C:\path" } | Should -Be "C:\path"
+ }
+
+ It "Writes path correctly when provided through array of hashtable" {
+ Format-PesterPath -Path @{ Path = "C:\path1" }, @{ Path = "C:\path2" } -Delimiter ', ' | Should -Be "C:\path1, C:\path2"
+ }
- It "Writes path correctly when provided through array of hashtable" {
- Format-PesterPath -Path @{ Path = "C:\path1" }, @{ Path = "C:\path2" } -Delimiter ', ' | Should -Be "C:\path1, C:\path2"
}
}
Describe "Write-PesterStart" {
It "uses Format-PesterPath with the provided path" {
Mock Format-PesterPath
- $expected = "C:\temp"
+
+ If ((GetPesterOS) -ne 'Windows'){
+
+ $expected = "/tmp"
+
+ }
+ Else {
+
+ $expected = "C:\temp"
+
+ }
+
Write-PesterStart -PesterState (New-PesterState) -Path $expected
Assert-MockCalled Format-PesterPath -ParameterFilter {$Path -eq $expected}
}
@@ -162,6 +198,7 @@ InModuleScope -ModuleName Pester -ScriptBlock {
}
It 'failed should produces correct message lines.' {
try { 'One' | Should be 'Two' } catch { $e = $_ }
+
$r = $e | ConvertTo-FailureLines
$r.Message[0] | Should be 'String lengths are both 3. Strings differ at index 0.'
@@ -228,13 +265,29 @@ InModuleScope -ModuleName Pester -ScriptBlock {
}
if ( $e | Get-Member -Name ScriptStackTrace )
{
- It 'produces correct trace lines.' {
- $r.Trace[0] | Should be "at f1, $testPath`: line 2"
- $r.Trace[1] | Should be "at f2, $testPath`: line 5"
- $r.Trace[2] | Should be "at , $testPath`: line 7"
- $r.Trace[3] -match 'at , .*\\Functions\\Output.Tests.ps1: line [0-9]*$' |
- Should be $true
- $r.Trace.Count | Should be 5
+ If ((GetPesterOS) -ne 'Windows') {
+
+ It 'produces correct trace lines.' {
+ $r.Trace[0] | Should be "at f1, $testPath`: line 2"
+ $r.Trace[1] | Should be "at f2, $testPath`: line 5"
+ $r.Trace[2] | Should be "at , $testPath`: line 7"
+ $r.Trace[3] -match 'at , .*/Functions/Output.Tests.ps1: line [0-9]*$' |
+ Should be $true
+ $r.Trace.Count | Should be 5
+ }
+
+ }
+ Else {
+
+ It 'produces correct trace lines.' {
+ $r.Trace[0] | Should be "at f1, $testPath`: line 2"
+ $r.Trace[1] | Should be "at f2, $testPath`: line 5"
+ $r.Trace[2] | Should be "at , $testPath`: line 7"
+ $r.Trace[3] -match 'at , .*\\Functions\\Output.Tests.ps1: line [0-9]*$' |
+ Should be $true
+ $r.Trace.Count | Should be 5
+ }
+
}
}
else
@@ -274,10 +327,19 @@ InModuleScope -ModuleName Pester -ScriptBlock {
}
if ( $e | Get-Member -Name ScriptStackTrace )
{
- It 'produces correct trace line.' {
- $r.Trace[0] | Should be "at , $testPath`: line 10"
- $r.Trace[1] -match 'at , .*\\Functions\\Output.Tests.ps1: line [0-9]*$'
- $r.Trace.Count | Should be 3
+ If ((GetPesterOS) -ne 'Windows') {
+ It 'produces correct trace line.' {
+ $r.Trace[0] | Should be "at , $testPath`: line 10"
+ $r.Trace[1] -match 'at , .*/Functions/Output.Tests.ps1: line [0-9]*$'
+ $r.Trace.Count | Should be 3
+ }
+ }
+ Else {
+ It 'produces correct trace line.' {
+ $r.Trace[0] | Should be "at , $testPath`: line 10"
+ $r.Trace[1] -match 'at , .*\\Functions\\Output.Tests.ps1: line [0-9]*$'
+ $r.Trace.Count | Should be 3
+ }
}
}
else
diff --git a/Functions/Output.ps1 b/Functions/Output.ps1
index 518569097..f6effc147 100644
--- a/Functions/Output.ps1
+++ b/Functions/Output.ps1
@@ -126,7 +126,7 @@ function Write-Describe {
& $SafeCommands['Write-Host'] "${margin}${Text}" -ForegroundColor $ReportTheme.Describe
# If the feature has a longer description, write that too
if($Describe.PSObject.Properties['Description'] -and $Describe.Description) {
- $Describe.Description -split '\n' | ForEach {
+ $Describe.Description -split "$([System.Environment]::NewLine)" | ForEach {
& $SafeCommands['Write-Host'] ($ReportStrings.Margin * ($pester.IndentLevel + 1)) $_ -ForegroundColor $ReportTheme.DescribeDetail
}
}
@@ -150,7 +150,7 @@ function Write-Context {
& $SafeCommands['Write-Host'] ($ReportStrings.Margin + $Text) -ForegroundColor $ReportTheme.Context
# If the scenario has a longer description, write that too
if($Context.PSObject.Properties['Description'] -and $Context.Description) {
- $Context.Description -split '\n' | ForEach {
+ $Context.Description -split "$([System.Environment]::NewLine)" | ForEach {
& $SafeCommands['Write-Host'] (" " * $ReportStrings.Context.Length) $_ -ForegroundColor $ReportTheme.ContextDetail
}
}
@@ -159,19 +159,20 @@ function Write-Context {
function ConvertTo-PesterResult {
param(
+ [String] $Name,
[Nullable[TimeSpan]] $Time,
[System.Management.Automation.ErrorRecord] $ErrorRecord
)
$testResult = @{
- name = $name
+ name = $Name
time = $time
failureMessage = ""
stackTrace = ""
ErrorRecord = $null
success = $false
result = "Failed"
- };
+ }
if(-not $ErrorRecord)
{
@@ -211,7 +212,7 @@ function ConvertTo-PesterResult {
}
$testResult.failureMessage = $failureMessage
- $testResult.stackTrace = "at , ${file}: line ${line}`n${line}: ${Text}"
+ $testResult.stackTrace = "at , ${file}: line ${line}$([System.Environment]::NewLine)${line}: ${Text}"
$testResult.ErrorRecord = $ErrorRecord
return $testResult
@@ -322,9 +323,23 @@ function Write-PesterReport {
$Pending = if($PesterState.PendingCount -gt 0) { $ReportTheme.Pending } else { $ReportTheme.Information }
$Inconclusive = if($PesterState.InconclusiveCount -gt 0) { $ReportTheme.Inconclusive } else { $ReportTheme.Information }
+ Try {
+ $PesterStatePassedScenariosCount = $PesterState.PassedScenarios.Count
+ }
+ Catch {
+ $PesterStatePassedScenariosCount = 0
+ }
+
+ Try {
+ $PesterStateFailedScenariosCount = $PesterState.FailedScenarios.Count
+ }
+ Catch {
+ $PesterStateFailedScenariosCount = 0
+ }
+
if($ReportStrings.ContextsPassed) {
- & $SafeCommands['Write-Host'] ($ReportStrings.ContextsPassed -f $PesterState.PassedScenarios.Count) -Foreground $Success -NoNewLine
- & $SafeCommands['Write-Host'] ($ReportStrings.ContextsFailed -f $PesterState.FailedScenarios.Count) -Foreground $Failure
+ & $SafeCommands['Write-Host'] ($ReportStrings.ContextsPassed -f $PesterStatePassedScenariosCount) -Foreground $Success -NoNewLine
+ & $SafeCommands['Write-Host'] ($ReportStrings.ContextsFailed -f $PesterStateFailedScenariosCount) -Foreground $Failure
}
if($ReportStrings.TestsPassed) {
& $SafeCommands['Write-Host'] ($ReportStrings.TestsPassed -f $PesterState.PassedCount) -Foreground $Success -NoNewLine
@@ -391,10 +406,11 @@ function ConvertTo-FailureLines
## convert the exception messages
$exception = $ErrorRecord.Exception
$exceptionLines = @()
+
while ($exception)
{
$exceptionName = $exception.GetType().Name
- $thisLines = $exception.Message.Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries)
+ $thisLines = $exception.Message.Split([string[]]($([System.Environment]::NewLine),"\n","`n"), [System.StringSplitOptions]::RemoveEmptyEntries)
if ($ErrorRecord.FullyQualifiedErrorId -ne 'PesterAssertionFailed')
{
$thisLines[0] = "$exceptionName`: $($thisLines[0])"
@@ -407,7 +423,7 @@ function ConvertTo-FailureLines
$lines.Message += $exceptionLines
if ($ErrorRecord.FullyQualifiedErrorId -eq 'PesterAssertionFailed')
{
- $lines.Message += "$($ErrorRecord.TargetObject.Line)`: $($ErrorRecord.TargetObject.LineText)".Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries)
+ $lines.Message += "$($ErrorRecord.TargetObject.Line)`: $($ErrorRecord.TargetObject.LineText)".Split([string[]]($([System.Environment]::NewLine),"\n","`n"), [System.StringSplitOptions]::RemoveEmptyEntries)
}
if ( -not ($ErrorRecord | & $SafeCommands['Get-Member'] -Name ScriptStackTrace) )
@@ -424,14 +440,29 @@ function ConvertTo-FailureLines
}
## convert the stack trace
- $traceLines = $ErrorRecord.ScriptStackTrace.Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries)
+ $traceLines = $ErrorRecord.ScriptStackTrace.Split([string[]]($([System.Environment]::NewLine),"\n","`n"), [System.StringSplitOptions]::RemoveEmptyEntries)
$count = 0
# omit the lines internal to Pester
+
+ If ((GetPesterOS) -ne 'Windows') {
+
+ [String]$pattern1 = '^at (Invoke-Test|Context|Describe|InModuleScope|Invoke-Pester), .*/Functions/.*.ps1: line [0-9]*$'
+ [String]$pattern2 = '^at Should, .*/Functions/Assertions/Should.ps1: line [0-9]*$'
+ [String]$pattern3 = '^at Assert-MockCalled, .*/Functions/Mock.ps1: line [0-9]*$'
+ }
+ Else {
+
+ [String]$pattern1 = '^at (Invoke-Test|Context|Describe|InModuleScope|Invoke-Pester), .*\\Functions\\.*.ps1: line [0-9]*$'
+ [String]$pattern2 = '^at Should, .*\\Functions\\Assertions\\Should.ps1: line [0-9]*$'
+ [String]$pattern3 = '^at Assert-MockCalled, .*\\Functions\\Mock.ps1: line [0-9]*$'
+
+ }
+
foreach ( $line in $traceLines )
{
- if ( $line -match '^at (Invoke-Test|Context|Describe|InModuleScope|Invoke-Pester), .*\\Functions\\.*.ps1: line [0-9]*$' )
+ if ( $line -match $pattern1 )
{
break
}
@@ -440,8 +471,8 @@ function ConvertTo-FailureLines
$lines.Trace += $traceLines |
& $SafeCommands['Select-Object'] -First $count |
& $SafeCommands['Where-Object'] {
- $_ -notmatch '^at Should, .*\\Functions\\Assertions\\Should.ps1: line [0-9]*$' -and
- $_ -notmatch '^at Assert-MockCalled, .*\\Functions\\Mock.ps1: line [0-9]*$'
+ $_ -notmatch $pattern2 -and
+ $_ -notmatch $pattern3
}
return $lines
diff --git a/Functions/TestResults.Tests.ps1 b/Functions/TestResults.Tests.ps1
index 235ada3d1..7eb2adb14 100644
--- a/Functions/TestResults.Tests.ps1
+++ b/Functions/TestResults.Tests.ps1
@@ -12,7 +12,7 @@ InModuleScope Pester {
$TestResults.AddTestResult("Successful testcase",'Passed',(New-TimeSpan -Seconds 1))
#export and validate the file
- $testFile = "$TestDrive\Results\Tests.xml"
+ [String]$testFile = "$TestDrive{0}Results{0}Tests.xml" -f [System.IO.Path]::DirectorySeparatorChar
Export-NunitReport $testResults $testFile
$xmlResult = [xml] (Get-Content $testFile)
$xmlTestCase = $xmlResult.'test-results'.'test-suite'.'results'.'test-suite'.'results'.'test-case'
@@ -29,7 +29,7 @@ InModuleScope Pester {
$TestResults.AddTestResult("Failed testcase",'Failed',$time,'Assert failed: "Expected: Test. But was: Testing"','at line: 28 in C:\Pester\Result.Tests.ps1')
#export and validate the file
- $testFile = "$TestDrive\Results\Tests.xml"
+ [String]$testFile = "$TestDrive{0}Results{0}Tests.xml" -f [System.IO.Path]::DirectorySeparatorChar
Export-NunitReport $testResults $testFile
$xmlResult = [xml] (Get-Content $testFile)
$xmlTestCase = $xmlResult.'test-results'.'test-suite'.'results'.'test-suite'.'results'.'test-case'
@@ -47,7 +47,7 @@ InModuleScope Pester {
$TestResults.AddTestResult("Testcase",'Passed',(New-TimeSpan -Seconds 1))
#export and validate the file
- $testFile = "$TestDrive\Results\Tests.xml"
+ [String]$testFile = "$TestDrive{0}Results{0}Tests.xml" -f [System.IO.Path]::DirectorySeparatorChar
Export-NunitReport $testResults $testFile
$xmlResult = [xml] (Get-Content $testFile)
$xmlTestResult = $xmlResult.'test-results'
@@ -68,7 +68,7 @@ InModuleScope Pester {
Set-PesterStatistics -Node $TestResults.TestActions
#export and validate the file
- $testFile = "$TestDrive\Results\Tests.xml"
+ [String]$testFile = "$TestDrive{0}Results{0}Tests.xml" -f [System.IO.Path]::DirectorySeparatorChar
Export-NunitReport $testResults $testFile
$xmlResult = [xml] (Get-Content $testFile)
@@ -94,7 +94,7 @@ InModuleScope Pester {
Set-PesterStatistics -Node $TestResults.TestActions
#export and validate the file
- $testFile = "$TestDrive\Results\Tests.xml"
+ [String]$testFile = "$TestDrive{0}Results{0}Tests.xml" -f [System.IO.Path]::DirectorySeparatorChar
Export-NunitReport $testResults $testFile
$xmlResult = [xml] (Get-Content $testFile)
@@ -115,7 +115,7 @@ InModuleScope Pester {
it "should write the environment information" {
$state = New-PesterState "."
- $testFile = "$TestDrive\Results\Tests.xml"
+ [String]$testFile = "$TestDrive{0}Results{0}Tests.xml" -f [System.IO.Path]::DirectorySeparatorChar
Export-NunitReport $state $testFile
$xmlResult = [xml] (Get-Content $testFile)
@@ -139,7 +139,7 @@ InModuleScope Pester {
$TestResults.AddTestResult("Failed testcase",'Failed',(New-TimeSpan -Seconds 2))
#export and validate the file
- $testFile = "$TestDrive\Results\Tests.xml"
+ [String]$testFile = "$TestDrive{0}Results{0}Tests.xml" -f [System.IO.Path]::DirectorySeparatorChar
Export-NunitReport $testResults $testFile
$xml = [xml] (Get-Content $testFile)
@@ -156,7 +156,7 @@ InModuleScope Pester {
$TestResults.LeaveTestGroup('Describe -!@#$%^&*()_+`1234567890[];'',./"- #1', 'Describe')
#export and validate the file
- $testFile = "$TestDrive\Results\Tests.xml"
+ [String]$testFile = "$TestDrive{0}Results{0}Tests.xml" -f [System.IO.Path]::DirectorySeparatorChar
Export-NunitReport $testResults $testFile
$xml = [xml] (Get-Content $testFile)
@@ -196,7 +196,7 @@ InModuleScope Pester {
)
#export and validate the file
- $testFile = "$TestDrive\Results\Tests.xml"
+ [String]$testFile = "$TestDrive{0}Results{0}Tests.xml" -f [System.IO.Path]::DirectorySeparatorChar
Export-NunitReport $testResults $testFile
$xmlResult = [xml] (Get-Content $testFile)
@@ -285,8 +285,15 @@ InModuleScope Pester {
$p | Should Be (Join-Path $TestDrive existingfile.txt)
}
+ If (($PSVersionTable.ContainsKey('PSEdition')) -and ($PSVersionTable.PSEdition -eq 'Core')) {
+ $CommandToTest = "pwsh"
+ }
+ Else {
+ $CommandToTest = "powershell"
+ }
+
It "Resolves full path correctly" {
- $powershellPath = Get-Command 'powershell' | Select -ExpandProperty 'Definition'
+ $powershellPath = Get-Command -Name $CommandToTest | Select-Object -ExpandProperty 'Definition'
$powershellPath | Should -Not -BeNullOrEmpty
GetFullPath $powershellPath | Should Be $powershellPath
diff --git a/Functions/TestResults.ps1 b/Functions/TestResults.ps1
index 3e3cdfa54..80a50796d 100644
--- a/Functions/TestResults.ps1
+++ b/Functions/TestResults.ps1
@@ -437,6 +437,18 @@ function Get-RunTimeEnvironment() {
Version = "0.0.0.0"
}
}
+
+ If ( ($PSVersionTable.ContainsKey('PSEdition')) -and ($PSVersionTable.PSEdition -EQ 'Core')) {
+
+ $CLrVersion = "Unknown"
+
+ }
+ Else {
+
+ $CLrVersion = [string]$PSVersionTable.ClrVersion
+
+ }
+
@{
'nunit-version' = '2.5.8.0'
'os-version' = $osSystemInformation.Version
@@ -445,7 +457,7 @@ function Get-RunTimeEnvironment() {
'machine-name' = $env:ComputerName
user = $env:Username
'user-domain' = $env:userDomain
- 'clr-version' = [string]$PSVersionTable.ClrVersion
+ 'clr-version' = $CLrVersion
}
}
diff --git a/Pester.Tests.ps1 b/Pester.Tests.ps1
index 6455f5134..855eb3a33 100644
--- a/Pester.Tests.ps1
+++ b/Pester.Tests.ps1
@@ -26,11 +26,11 @@ Describe -Tags 'VersionChecks' "Pester manifest and changelog" {
$script:manifest.Guid | Should Be 'a699dea5-2c73-4616-a270-1f7abb777e71'
}
- if (Get-Command git.exe -ErrorAction SilentlyContinue) {
+ if (Get-Command -Name git -ErrorAction SilentlyContinue) {
$skipVersionTest = -not [bool]((git remote -v 2>&1) -match "github.com/Pester/")
It "is tagged with a valid version" -skip:$skipVersionTest {
- $thisCommit = git.exe log --decorate --oneline HEAD~1..HEAD
+ $thisCommit = git log --decorate --oneline HEAD~1..HEAD
if ($thisCommit -match 'tag:\s*(\d+(?:\.\d+)*)')
{
@@ -167,7 +167,7 @@ Describe 'Style rules' -Tag StyleRules {
if ($badLines.Count -gt 0)
{
- throw "The following $($badLines.Count) lines contain trailing whitespace: `r`n`r`n$($badLines -join "`r`n")"
+ throw "The following $($badLines.Count) lines contain trailing whitespace: $([System.Environment]::NewLine)$([System.Environment]::NewLine)$($badLines -join "$([System.Environment]::NewLine)")"
}
}
It 'Spaces are used for indentation in all code files, not tabs' {
@@ -188,7 +188,7 @@ Describe 'Style rules' -Tag StyleRules {
if ($badLines.Count -gt 0)
{
- throw "The following $($badLines.Count) lines start with a tab character: `r`n`r`n$($badLines -join "`r`n")"
+ throw "The following $($badLines.Count) lines start with a tab character: $([System.Environment]::NewLine)$([System.Environment]::NewLine)$($badLines -join "$([System.Environment]::NewLine)")"
}
}
@@ -203,7 +203,7 @@ Describe 'Style rules' -Tag StyleRules {
)
if ($badFiles.Count -gt 0) {
- throw "The following files do not end with a newline: `r`n`r`n$($badFiles -join "`r`n")"
+ throw "The following files do not end with a newline: $([System.Environment]::NewLine)$([System.Environment]::NewLine)$($badFiles -join "$([System.Environment]::NewLine)")"
}
}
}
diff --git a/Pester.psm1 b/Pester.psm1
index 6226e9807..bf5dd7889 100644
--- a/Pester.psm1
+++ b/Pester.psm1
@@ -86,7 +86,7 @@ $script:SafeCommands = @{
'Write-Warning' = Get-Command -Name Write-Warning -Module Microsoft.PowerShell.Utility @safeCommandLookupParameters
}
-# Not all platforms have Get-WmiObject (Nano)
+# Not all platforms have Get-WmiObject (Nano or PSCore 6.0.0-beta.x on Linux)
# Get-CimInstance is prefered, but we can use Get-WmiObject if it exists
# Moreover, it shouldn't really be fatal if neither of those cmdlets
# exist
diff --git a/README.md b/README.md
index a2d9904d3..237602474 100644
--- a/README.md
+++ b/README.md
@@ -55,7 +55,8 @@ Learn more about the [usage and syntax](https://github.com/Pester/Pester/wiki) o
## Installation
-Pester is compatible with Windows 10, 8, 7, Vista and even 2003. We are also working hard on making it run on Linux and MacOS.
+Pester is compatible with Windows PowerShell 2.x - 5.x on Windows 10, 8, 7, Vista and even 2003.
+Since version 4.0.9 Pester is compatible also with PowerShell Core 6.x on Windows, Linux, macOS but with some [limitations](https://github.com/pester/Pester/wiki/Pester-on-PSCore-limitations).
Pester comes pre-installed with Windows 10, but we recommend updating, by running this PowerShell command _as administrator_:
@@ -65,6 +66,12 @@ Install-Module -Name Pester -Force -SkipPublisherCheck
Not running Windows 10 or facing problems? See the [full installation and update guide](https://github.com/pester/Pester/wiki/Installation-and-Update).
+Please be aware that PowerShell Core 6.0.0-beta.9 comes with bundle Pester version 3.3.9, but we recommend updating, by running this PowerShell command _as administrator_:
+
+```powershell
+Install-Module -Name Pester -Force
+```
+
## Features
### Test runner