Checks/Script.Tests.ps1
param( [parameter(Mandatory = $true)] [string[]]$Source, [parameter(Mandatory = $false)] [string]$SonarQubeRules ) BeforeDiscovery { $scriptFiles = @() $Source | ForEach-Object { $fileProperties = (Get-Item -Path $_) $scriptFiles += @{ 'FullName' = $_ 'Name' = $fileProperties.Name 'Directory' = $fileProperties.Directory } } } Describe "Script Tests" { Context "Script: <_.Name> at <_.Directory>" -ForEach $scriptFiles { BeforeEach { $scriptFile = $_.FullName $fileContent = Get-FileContent -Path $_.FullName if (-not([string]::IsNullOrEmpty($fileContent))) { ($ParsedFile, $ErrorCount) = Get-ParsedContent -Content $fileContent } else { Write-Warning "File is empty" $ParsedFile = $null $ErrorCount = 1 } } It "check script has valid PowerShell syntax" { $ErrorCount | Should -Be 0 } It "check help must contain required elements" { { $helpComments = ($ParsedFile | Where-Object { $_.Type -eq "Comment" } | Select-Object -First 1) if ([string]::IsNullOrEmpty($helpComments)) { throw "No help block found" } $helpTokens = Convert-Help -Help $helpComments.Content Test-RequiredToken -HelpTokens $helpTokens } | Should -Not -Throw } It "check help must not contain unspecified elements" { { $helpComments = ($ParsedFile | Where-Object { $_.Type -eq "Comment" } | Select-Object -First 1) if ([string]::IsNullOrEmpty($helpComments)) { throw "No help block found" } $helpTokens = Convert-Help -Help $helpComments.Content Test-UnspecifiedToken -HelpTokens $helpTokens } | Should -Not -Throw } It "check help elements text is not empty" { { $helpComments = ($ParsedFile | Where-Object { $_.Type -eq "Comment" } | Select-Object -First 1) if ([string]::IsNullOrEmpty($helpComments)) { throw "No help block found" } $helpTokens = Convert-Help -Help $helpComments.Content Test-HelpTokensTextIsValid -HelpTokens $helpTokens } | Should -Not -Throw } It "check help elements Min/Max counts are valid" { { $helpComments = ($ParsedFile | Where-Object { $_.Type -eq "Comment" } | Select-Object -First 1) if ([string]::IsNullOrEmpty($helpComments)) { throw "No help block found" } $helpTokens = Convert-Help -Help $helpComments.Content Test-HelpTokensCountIsValid -HelpTokens $helpTokens } | Should -Not -Throw } It "check script contains [CmdletBinding] attribute" { $cmdletBindingCount = (@(Get-TokenMarker -ParsedContent $ParsedFile -Type "Attribute" -Content "CmdletBinding")).Count $cmdletBindingCount | Should -Be 1 } It "check script contains [OutputType] attribute" { $outputTypeCount = (@(Get-TokenMarker -ParsedContent $ParsedFile -Type "Attribute" -Content "OutputType")).Count $outputTypeCount | Should -Be 1 } It "check script [OutputType] attribute is not empty" { $outputTypeToken = (Get-Token -ParsedContent $ParsedFile -Type "Attribute" -Content "OutputType") $outputTypeValue = @($outputTypeToken | Where-Object { $_.Type -eq "Type" }) $outputTypeValue | Should -Not -BeNullOrEmpty } It "check script contains param attribute" { $paramCount = (@(Get-TokenMarker -ParsedContent $ParsedFile -Type "Keyword" -Content "param")).Count $paramCount | Should -Be 1 } It "check script param block variables have type" { $parameterVariables = Get-ScriptParameter -Content $fileContent if ($parameterVariables.Count -eq 0) { Set-ItResult -Inconclusive -Because "No parameters found" } { Test-ParameterVariablesHaveType -ParameterVariables $parameterVariables } | Should -Not -Throw } It "check .PARAMETER help matches variables in param block" { { $helpComments = ($ParsedFile | Where-Object { $_.Type -eq "Comment" } | Select-Object -First 1) if ([string]::IsNullOrEmpty($helpComments)) { throw "No help block found" } $parameterVariables = Get-ScriptParameter -Content $fileContent $helpTokens = Convert-Help -Help $helpComments.Content Test-HelpTokensParamsMatch -HelpTokens $helpTokens -ParameterVariables $parameterVariables } | Should -Not -Throw } It "check script contains no PSScriptAnalyzer suppressions" { $suppressCount = (@(Get-TokenMarker -ParsedContent $ParsedFile -Type "Attribute" -Content "Diagnostics.CodeAnalysis.SuppressMessageAttribute")).Count $suppressCount | Should -Be 0 } It "check script contains no PSScriptAnalyzer failures" { $AnalyserFailures = @(Invoke-ScriptAnalyzer -Path $scriptFile) ($AnalyserFailures | ForEach-Object { $_.Message }) | Should -BeNullOrEmpty } It "check script contains no PSScriptAnalyser SonarQube rule failures" { if ( [string]::IsNullOrEmpty($SonarQubeRules) ) { Set-ItResult -Inconclusive -Because "No SonarQube PSScriptAnalyzer rules folder specified" } if ( -not (Test-Path -Path $SonarQubeRules -ErrorAction SilentlyContinue)) { Set-ItResult -Inconclusive -Because "SonarQube PSScriptAnalyzer rules not found" } $AnalyserFailures = @(Invoke-ScriptAnalyzer -Path $scriptFile -CustomRulePath $SonarQubeRules) $AnalyserFailures | ForEach-Object { $_.Message } | Should -BeNullOrEmpty } It "check Import-Module statements have valid format" { $importModuleTokens = @($ParsedFile | Where-Object { $_.Type -eq "Command" -and $_.Content -eq "Import-Module" }) if ($importModuleTokens.Count -eq 0) { Set-ItResult -Inconclusive -Because "No Import-Module statements found" } { Test-ImportModuleIsValid -ParsedContent $ParsedFile -ImportModuleTokens $importModuleTokens } | Should -Not -Throw } } } |