PSJira.Tests.ps1
$here = Split-Path -Parent $MyInvocation.MyCommand.Path $projectRoot = Split-Path -Parent $here $moduleRoot = "$projectRoot\PSJira" $manifestFile = "$moduleRoot\PSJira.psd1" $changelogFile = "$projectRoot\CHANGELOG.md" $appveyorFile = "$projectRoot\appveyor.yml" $publicFunctions = "$moduleRoot\Public" $internalFunctions = "$moduleRoot\Internal" Describe "PSJira" { Context "All required tests are present" { # We want to make sure that every .ps1 file in the Functions directory that isn't a Pester test has an associated Pester test. # This helps keep me honest and makes sure I'm testing my code appropriately. It "Includes a test for each PowerShell function in the module" { Get-ChildItem -Path $publicFunctions -Filter "*.ps1" -Recurse | Where-Object -FilterScript {$_.Name -notlike '*.Tests.ps1'} | % { $_.FullName -replace '.ps1','.Tests.ps1' | Should Exist } } } Context "Manifest, changelog, and AppVeyor" { # These tests are...erm, borrowed...from the module tests from the Pester module. # I think they are excellent for sanity checking, and all credit for the following # tests goes to Dave Wyatt, the genius behind Pester. I've just adapted them # slightly to match PSJira. $script:manifest = $null It "Includes a valid manifest file" { { $script:manifest = Test-ModuleManifest -Path $script:manifestFile -ErrorAction Stop -WarningAction SilentlyContinue } | Should Not Throw } # There is a bug that prevents Test-ModuleManifest from updating correctly when the manifest file changes. See here: # https://connect.microsoft.com/PowerShell/feedback/details/1541659/test-modulemanifest-the-psmoduleinfo-is-not-updated # As a temp workaround, we'll just read the manifest as a raw hashtable. # Credit to this workaround comes from here: # https://psescape.azurewebsites.net/pester-testing-your-module-manifest/ $script:manifest = Invoke-Expression (Get-Content $script:manifestFile -Raw) It "Manifest file includes the correct root module" { $script:manifest.RootModule | Should Be 'PSJira.psm1' } It "Manifest file includes the correct guid" { $script:manifest.Guid | Should Be '4bf3eb15-037e-43b7-9e47-20a30436324f' } It "Manifest file includes a valid version" { # $script:manifest.Version -as [Version] | Should Not BeNullOrEmpty $script:manifest.ModuleVersion -as [Version] | Should Not BeNullOrEmpty } It "Includes a changelog file" { $changelogFile | Should Exist } $changelogVersion = $null It "Changelog includes a valid version number" { foreach ($line in (Get-Content $changelogFile)) { if ($line -match "^\D*(?<Version>(\d+\.){1,3}\d+)") { $changelogVersion = $matches.Version break } } $changelogVersion | Should Not BeNullOrEmpty $changelogVersion -as [Version] | Should Not BeNullOrEmpty } It "Changelog version matches manifest version" { $changelogVersion -as [Version] | Should Be ( $script:manifest.Version -as [Version] ) } # Back to me! Pester doesn't use AppVeyor, as far as I know, and I do. It "Includes an appveyor.yml file" { $appveyorFile | Should Exist } It "Appveyor.yml file includes the module version" { foreach ($line in (Get-Content $appveyorFile)) { # (?<Version>()) - non-capturing group, but named Version. This makes it # easy to reference the inside group later. if ($line -match '^\D*(?<Version>(\d+\.){1,3}\d+).\{build\}') { $appveyorVersion = $matches.Version break } } $appveyorVersion | Should Not BeNullOrEmpty $appveyorVersion -as [Version] | Should Not BeNullOrEmpty } It "Appveyor version matches manifest version" { $appveyorVersion -as [Version] | Should Be ( $script:manifest.Version -as [Version] ) } } Context "Function checking" { $functionFiles = Get-ChildItem $publicFunctions -Filter *.ps1 | Select-Object -ExpandProperty BaseName | Where-Object { $_ -notlike "*.Tests" } $internalFiles = Get-ChildItem $internalFunctions -Filter *.ps1 | Select-Object -ExpandProperty BaseName | Where-Object { $_ -notlike "*.Tests" } #$exportedFunctions = $script:manifest.ExportedFunctions.Values.Name $exportedFunctions = $script:manifest.FunctionsToExport foreach ($f in $functionFiles) { It "Exports $f" { $exportedFunctions -contains $f | Should Be $true } } foreach ($f in $internalFiles) { It "Does not export $f" { $exportedFunctions -contains $f | Should Be $false } } } Context "Style checking" { # This section is again from the mastermind, Dave Wyatt. Again, credit # goes to him for these tests. $files = @( Get-ChildItem $here -Include *.ps1,*.psm1 Get-ChildItem $publicFunctions -Include *.ps1,*.psm1 -Recurse ) It 'Source files contain no trailing whitespace' { $badLines = @( foreach ($file in $files) { $lines = [System.IO.File]::ReadAllLines($file.FullName) $lineCount = $lines.Count for ($i = 0; $i -lt $lineCount; $i++) { if ($lines[$i] -match '\s+$') { 'File: {0}, Line: {1}' -f $file.FullName, ($i + 1) } } } ) if ($badLines.Count -gt 0) { throw "The following $($badLines.Count) lines contain trailing whitespace: `r`n`r`n$($badLines -join "`r`n")" } } It 'Source files all end with a newline' { $badFiles = @( foreach ($file in $files) { $string = [System.IO.File]::ReadAllText($file.FullName) if ($string.Length -gt 0 -and $string[-1] -ne "`n") { $file.FullName } } ) if ($badFiles.Count -gt 0) { throw "The following files do not end with a newline: `r`n`r`n$($badFiles -join "`r`n")" } } } } |