Skip to content
This repository has been archived by the owner on Feb 24, 2021. It is now read-only.

Add function to run tests more consistently #87

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 124 additions & 1 deletion TestRunner.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,127 @@ function Start-DscResourceTests
Pop-Location
}

Export-ModuleMember -Function @( 'Start-DscResourceTests' )
<#
.SYNOPSIS
Runs Pester tests and reports results

.PARAMETER Path
The Path to the tests to run

.PARAMETER CodeCoverage
An array of paths to files to run CodeCoverage for.

.EXAMPLE
Invoke-DscResourceTests -Path C:\myModule\tests -CodeCoverage @('C:\myModule\myModule.psm1')

#>
function Invoke-DscResourceTests {
[CmdletBinding()]
param
(
[CmdletBinding()]
[string]
$Path,

[Object[]]
$CodeCoverage
)

Write-Info "Running tests: $Path"
$testResultPath = 'TestsResults.xml'

$results = Invoke-Pester -OutputFormat NUnitXml -OutputFile $testResultPath -PassThru @PSBoundParameters

if(${env:APPVEYOR_JOB_ID})
{
foreach($result in $results.TestResult)
{
[string] $describeName = $result.Describe -replace '\\', '/'
[string] $contextName = $result.Context -replace '\\', '/'
$componentName = '{0}; Context: {1}' -f $describeName, $contextName

#Write-Info ('Adding test result {0} - {1}, Outcome: {2}, Duration {3}' -f $componentName, $result.Name, $result.Result, $result.Time.TotalMilliseconds)
Add-AppveyorTest -Name $result.Name -Framework NUnit -Filename $componentName -Outcome $result.Result -Duration $result.Time.TotalMilliseconds
}
}
else {
Write-Info 'Not in AppVeyor. Skipping uploading test results.'
}


Push-TestArtifact -Path $testResultPath

Write-Info 'Done running tests.'
Write-Info "Test result Type: $($results.gettype().fullname)"

if ($results.FailedCount -gt 0)
{
throw "$($results.FailedCount) tests failed."
}

return $results
}

<#
.SYNOPSIS
Writes information to the build log

.PARAMETER Message
The Message to write

.EXAMPLE
Write-Info -Message "Some build info"

#>
function Write-Info {
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true, Position=0)]
[string]
$Message
)

Write-Host -ForegroundColor Yellow "[Build Info] [$([datetime]::UtcNow)] $message"
}

<#
.SYNOPSIS
Uploads test artifacts

.PARAMETER Path
The path to the test artifacts

.EXAMPLE
Push-TestArtifact -Path .\TestArtifact.log

#>
function Push-TestArtifact
{
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true, Position=0)]
[string]
$Path
)

$resolvedPath = (Resolve-Path $Path).ProviderPath
if(${env:APPVEYOR_JOB_ID})
{
<# does not work with Pester 4.0.2
$url = "https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)"
Write-Info -Message "Uploading Test Results: $resolvedPath ; to: $url"
(New-Object 'System.Net.WebClient').UploadFile($url, $resolvedPath)
#>

Write-Info -Message "Uploading Test Artifact: $resolvedPath"
Push-AppveyorArtifact $resolvedPath
}
else
{
Write-Info -Message "Test Artifact: $resolvedPath"
}
}

Export-ModuleMember -Function @( 'Start-DscResourceTests','Invoke-DscResourceTests' )
106 changes: 106 additions & 0 deletions TestRunner_Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<#
.SYNOPSIS
Tests for TestRunner.psm1. Name _tests so they will not run with every resource (as it breaks the loaded module and adds time).
#>

Set-StrictMode -Version 'Latest'
$errorActionPreference = 'Stop'
$moduleName = 'TestRunner'
$TestRunnerModulePath = Join-Path -Path $PSScriptRoot -ChildPath "$moduleName.psm1"
Import-Module -Name $TestRunnerModulePath -Force

try {

$moduleRootFilePath = Split-Path -Path $PSScriptRoot -Parent

Describe 'Invoke-DscResourceTests' {
Context -Name 'No params' -Fixture {
Mock -CommandName 'Invoke-Pester' -MockWith { return [PSCustomObject]@{fakeTestResult=$true}} -ModuleName $moduleName
Mock -CommandName 'Push-TestArtifact' -Verifiable -ModuleName $moduleName

$results = Invoke-DscResourceTests
It "Should call Invoke-Pester with no path" {
Assert-MockCalled -CommandName 'Invoke-Pester' -Times 1 -ParameterFilter {$null -eq $Script} -ModuleName $moduleName
}

It "Should call Invoke-Pest with no CodeCoverage" {
Assert-MockCalled -CommandName 'Invoke-Pester' -Times 1 -ParameterFilter {$null -eq $CodeCoverage} -ModuleName $moduleName
}

It "Should call Invoke-Pest with OutputFormat='NUnitXml'" {
Assert-MockCalled -CommandName 'Invoke-Pester' -Times 1 -ParameterFilter {'NUnitXml' -eq $OutputFormat} -ModuleName $moduleName
}

It "Should call Invoke-Pest with OutputFile!=null" {
Assert-MockCalled -CommandName 'Invoke-Pester' -Times 1 -ParameterFilter {$null -ne $OutputFile} -ModuleName $moduleName
}

It "Should call -Verifiable mocks" {
Assert-VerifiableMocks
}

It "should return test results" {
$results.fakeTestResult | should be $true
}
}

Context -Name 'Path param' -Fixture {
Mock -CommandName 'Invoke-Pester' -MockWith { return [PSCustomObject]@{fakeTestResult=$true}} -ModuleName $moduleName
Mock -CommandName 'Push-TestArtifact' -Verifiable -ModuleName $moduleName

$resourcePath = 'C:\myResource'
$results = Invoke-DscResourceTests -Path $resourcePath
It "Should call Invoke-Pester with specified path" {
Assert-MockCalled -CommandName 'Invoke-Pester' -Times 1 -ParameterFilter {$resourcePath -eq $Script} -ModuleName $moduleName
}

It "Should call Invoke-Pest with no CodeCoverage" {
Assert-MockCalled -CommandName 'Invoke-Pester' -Times 1 -ParameterFilter {$null -eq $CodeCoverage} -ModuleName $moduleName
}

It "Should call Invoke-Pest with OutputFormat='NUnitXml'" {
Assert-MockCalled -CommandName 'Invoke-Pester' -Times 1 -ParameterFilter {'NUnitXml' -eq $OutputFormat} -ModuleName $moduleName
}

It "Should call -Verifiable mocks" {
Assert-VerifiableMocks
}

It "should return test results" {
$results.fakeTestResult | should be $true
}
}

Context -Name 'CodeCoverage param' -Fixture {
Mock -CommandName 'Invoke-Pester' -MockWith { return [PSCustomObject]@{fakeTestResult=$true}} -ModuleName $moduleName
Mock -CommandName 'Push-TestArtifact' -Verifiable -ModuleName $moduleName

$codeCoveragePaths = @('C:\myResource\myResource.psm1','C:\myResource\myResourceHelper.psm1')
$results = Invoke-DscResourceTests -CodeCoverage $codeCoveragePaths
It "Should call Invoke-Pester with no path" {
Assert-MockCalled -CommandName 'Invoke-Pester' -Times 1 -ParameterFilter {$null -eq $Script} -ModuleName $moduleName
}

It "Should call Invoke-Pest with specificed CodeCoverage" {
Assert-MockCalled -CommandName 'Invoke-Pester' -Times 1 -ParameterFilter {!(Compare-Object -DifferenceObject $codeCoveragePaths -ReferenceObject $CodeCoverage)} -ModuleName $moduleName
}

It "Should call Invoke-Pest with OutputFormat='NUnitXml'" {
Assert-MockCalled -CommandName 'Invoke-Pester' -Times 1 -ParameterFilter {'NUnitXml' -eq $OutputFormat} -ModuleName $moduleName
}

It "Should call -Verifiable mocks" {
Assert-VerifiableMocks
}

It "should return test results" {
$results.fakeTestResult | should be $true
}
}
}
}
finally
{
Remove-Module -Name $moduleName -Force -ErrorAction SilentlyContinue
Import-Module -Name $TestRunnerModulePath -Force -Scope Global
}