Public/Test-PSBuildPester.ps1
function Test-PSBuildPester { <# .SYNOPSIS Execute Pester tests for module. .DESCRIPTION Execute Pester tests for module. .PARAMETER Path Directory Pester tests to execute. .PARAMETER ModuleName Name of Module to test. .PARAMETER OutputPath Output path to store Pester test results to. .PARAMETER OutputFormat Test result output format (NUnit). .PARAMETER CodeCoverage Switch to indicate that code coverage should be calculated. .PARAMETER CodeCoverageThreshold Threshold required to pass code coverage test (.90 = 90%). .PARAMETER CodeCoverageFiles Array of files to validate code coverage for. .PARAMETER ImportModule Import module from OutDir prior to running Pester tests. .EXAMPLE PS> Test-PSBuildPester -Path ./tests -ModuleName Mymodule -OutputPath ./out/testResults.xml Run Pester tests in ./tests and save results to ./out/testResults.xml #> [cmdletbinding()] param( [parameter(Mandatory)] [string]$Path, [string]$ModuleName, [string]$OutputPath, [string]$OutputFormat = 'NUnit2.5', [switch]$CodeCoverage, [double]$CodeCoverageThreshold, [string[]]$CodeCoverageFiles = @(), [switch]$ImportModule ) if (-not (Get-Module -Name Pester)) { Import-Module -Name Pester -ErrorAction Stop } try { if ($ImportModule) { # Remove any previously imported project modules and import from the output dir $ModuleOutputManifest = [IO.Path]::Combine($env:BHBuildOutput, "$($ModuleName).psd1") Get-Module $ModuleName | Remove-Module -Force Import-Module $ModuleOutputManifest -Force } Push-Location -LiteralPath $Path Import-Module Pester -MinimumVersion 5.0.0 $configuration = [PesterConfiguration]::Default $configuration.Output.Verbosity = 'Detailed' $configuration.Run.PassThru = $false $configuration.TestResult.Enabled = -not [string]::IsNullOrEmpty($OutputPath) $configuration.TestResult.OutputPath = $OutputPath $configuration.TestResult.OutputFormat = $OutputFormat if ($CodeCoverage.IsPresent) { $configuration.CodeCoverage.Enabled = $true if ($CodeCoverageFiles.Count -gt 0) { $configuration.CodeCoverage.Path = $CodeCoverageFiles } $configuration.CodeCoverage.OutputPath = 'coverage.xml' } $testResult = Invoke-Pester -Configuration $configuration -Verbose:$VerbosePreference if ($testResult.FailedCount -gt 0) { throw 'One or more Pester tests failed' } if ($CodeCoverage.IsPresent) { Write-Host "`nCode Coverage:`n" -ForegroundColor Yellow if (Test-Path coverage.xml) { $textInfo = (Get-Culture).TextInfo [xml]$testCoverage = Get-Content coverage.xml $ccReport = $testCoverage.report.counter.ForEach({ $total = [int]$_.missed + [int]$_.covered $perc = [Math]::Truncate([int]$_.covered / $total) [pscustomobject]@{ name = $textInfo.ToTitleCase($_.Type.ToLower()) percent = $perc } }) $ccfail = $false $ccFailMsgs = @() $ccReport.ForEach({ 'Code coverage type [{0}] on specified files: {1:p}' -f $_.name, $_.percent if ($_.percent -lt $CodeCoverageThreshold) { $ccFail = $true $ccFailMsgs += ('Code coverage: [{0}] is [{1:p}], which is less than the threshold of [{2:p}]' -f $_.name, $_.percent, $CodeCoverageThreshold) } }) if ($ccFail) { throw $ccFailMsgs } } else { Write-Error 'coverage.xml not found' } } } finally { Pop-Location Remove-Module $ModuleName -ErrorAction SilentlyContinue } } |