From 312b05f372ca43a35970cfa41874686e033ae387 Mon Sep 17 00:00:00 2001
From: Wojciech Sciesinski <it-praktyk@users.noreply.github.com>
Date: Sat, 11 Nov 2017 06:19:22 +0100
Subject: [PATCH] Update Pester to work on PowerShell Core at Windows, Linux,
 macOS (#925)

* Set repository to use Windows-style EOL

* Comparing semantic version strings prior to fetching dynamic parameters now works in Powershell 6.0.0-beta versions

* Add travis.yml for Linux

* Exclude Gherkin from run on PowerShell Core

* Correct macOS name

* Changes to handling chars of new lines

* Rename PowerShell executable name due to rename in v6.0.0-beta.9

* Customize the code to the specifics of systems other than Windows

* Correction of mistakes in the parameter name

* Adjust notation of paths to systems other than Windows

* Improvements to code need to run Pester when Set-StrictMode -Version Latest

* Small remark about lack of WMI on Linux

* Skip failing tests - PowerShell issue #4268

* Merge pull request #926 from GavinEke/patch-1

* Update Travis CI to run on both Linux and macOS

* Better Travis config

* Improve Travis config

* Update CHANGELOG and README about compatibility with PSCore 6.x
---
 .gitattributes                                |  13 +-
 .travis.yml                                   |  25 ++
 CHANGELOG.md                                  |   1 +
 Functions/Assertions/Be.Tests.ps1             |  14 +-
 .../Assertions/FileContentMatch.Tests.ps1     |   2 +-
 .../FileContentMatchExactly.Tests.ps1         |   2 +-
 .../FileContentMatchMultiline.Tests.ps1       |   4 +-
 Functions/Assertions/PesterThrow.Tests.ps1    |  36 +--
 Functions/Assertions/PesterThrow.ps1          |  10 +-
 Functions/Assertions/Set-TestInconclusive.ps1 |   2 +-
 Functions/Assertions/Should.ps1               |   2 +-
 Functions/Coverage.Tests.ps1                  |  67 +++--
 Functions/Coverage.ps1                        |  27 +-
 Functions/Describe.ps1                        |   2 +-
 Functions/Environment.Tests.ps1               |  16 +-
 Functions/Environment.ps1                     |   4 +-
 Functions/Gherkin.Tests.ps1                   |   5 +-
 Functions/Gherkin.ps1                         |   9 +-
 Functions/GherkinHook.Tests.ps1               |   4 +-
 Functions/GherkinStep.Tests.ps1               |   4 +-
 Functions/It.ps1                              |   2 +-
 Functions/Mock.Tests.ps1                      | 261 +++++++++++++-----
 Functions/Mock.ps1                            |  19 +-
 Functions/New-Fixture.ps1                     |   2 +-
 Functions/Output.Tests.ps1                    | 114 ++++++--
 Functions/Output.ps1                          |  57 +++-
 Functions/TestResults.Tests.ps1               |  27 +-
 Functions/TestResults.ps1                     |  14 +-
 Pester.Tests.ps1                              |  10 +-
 Pester.psm1                                   |   2 +-
 README.md                                     |   9 +-
 31 files changed, 534 insertions(+), 232 deletions(-)
 create mode 100644 .travis.yml

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 '<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE report PUBLIC "-//JACOCO//DTD Report 1.0//EN" "report.dtd"><report name="Pester (date)"><sessioninfo id="this" start="" dump="" /><counter type="INSTRUCTION" missed="1" covered="6" /><counter type="LINE" missed="1" covered="6" /><counter type="METHOD" missed="1" covered="3" /><counter type="CLASS" missed="0" covered="1" /></report>'
             }
             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 += "<?xml version=""1.0"" encoding=""UTF-8"" standalone=""no""?>`n"
-    $jaCoCoReport += "<report name="""">`n"
-    $jaCoCoReport += "<sessioninfo id=""this"" start="""" dump="""" />`n"
-    $jaCoCoReport += "<counter type=""INSTRUCTION"" missed="""" covered=""""/>`n"
-    $jaCoCoReport += "<counter type=""LINE"" missed="""" covered=""""/>`n"
-    $jaCoCoReport += "<counter type=""METHOD"" missed="""" covered=""""/>`n"
-    $jaCoCoReport += "<counter type=""CLASS"" missed="""" covered=""""/>`n"
+    $jaCoCoReport = "<?xml version=""1.0"" encoding=""UTF-8"" standalone=""no""?>$([System.Environment]::NewLine)"
+    $jaCoCoReport += "<report name="""">$([System.Environment]::NewLine)"
+    $jaCoCoReport += "<sessioninfo id=""this"" start="""" dump="""" />$([System.Environment]::NewLine)"
+    $jaCoCoReport += "<counter type=""INSTRUCTION"" missed="""" covered=""""/>$([System.Environment]::NewLine)"
+    $jaCoCoReport += "<counter type=""LINE"" missed="""" covered=""""/>$([System.Environment]::NewLine)"
+    $jaCoCoReport += "<counter type=""METHOD"" missed="""" covered=""""/>$([System.Environment]::NewLine)"
+    $jaCoCoReport += "<counter type=""CLASS"" missed="""" covered=""""/>$([System.Environment]::NewLine)"
     $jaCoCoReport += "</report>"
 
     [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 = "<!DOCTYPE report PUBLIC ""-//JACOCO//DTD Report 1.0//EN"" ""report.dtd"">`n"
+    $jaCoCoReportDocType = "<!DOCTYPE report PUBLIC ""-//JACOCO//DTD Report 1.0//EN"" ""report.dtd"">$([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 <ScriptBlock>, $testPath`: line 7"
-                    $r.Trace[3] -match 'at <ScriptBlock>, .*\\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 <ScriptBlock>, $testPath`: line 7"
+                        $r.Trace[3] -match 'at <ScriptBlock>, .*/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 <ScriptBlock>, $testPath`: line 7"
+                        $r.Trace[3] -match 'at <ScriptBlock>, .*\\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 <ScriptBlock>, $testPath`: line 10"
-                    $r.Trace[1] -match 'at <ScriptBlock>, .*\\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 <ScriptBlock>, $testPath`: line 10"
+                        $r.Trace[1] -match 'at <ScriptBlock>, .*/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 <ScriptBlock>, $testPath`: line 10"
+                        $r.Trace[1] -match 'at <ScriptBlock>, .*\\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 <ScriptBlock>, ${file}: line ${line}`n${line}: ${Text}"
+    $testResult.stackTrace = "at <ScriptBlock>, ${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<End>, .*/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<End>, .*\\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<End>, .*\\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