Skip to content

Commit

Permalink
Fix QA tests
Browse files Browse the repository at this point in the history
  • Loading branch information
johlju committed Jan 14, 2024
1 parent 56de8c5 commit b653037
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 71 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- SqlServerDsc
- Added build tasks to generate Wiki documentation for public commands.
- QA test to verify that each public command's script file starts with a
new line (needed until PR https://github.com/PoshCode/ModuleBuilder/pull/127
is merged and released).

### Fixed

Expand Down Expand Up @@ -49,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
It is run with the meta task `pack` which is run by the pipeline.
To run the meta task `docs` the SMO assemblies must be loaded into the
session, either by importing SqlServer module or loading SMO stubs.
- QA test improved to speed up quality testing.
- SqlSetup
- Updated integration tests to use PSResourceGet to download required modules.

Expand Down
130 changes: 59 additions & 71 deletions tests/QA/module.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ Describe 'Changelog Management' -Tag 'Changelog' {
}

It 'Changelog should have an Unreleased header' -Skip:$skipTest {
(Get-ChangelogData -Path (Join-Path -Path $ProjectPath -ChildPath 'CHANGELOG.md') -ErrorAction Stop).Unreleased | Should -Not -BeNullOrEmpty
(Get-ChangelogData -Path (Join-Path -Path $ProjectPath -ChildPath 'CHANGELOG.md') -ErrorAction Stop).Unreleased | Should -Not -BeNullOrEmpty
}
}

Expand All @@ -125,14 +125,25 @@ BeforeDiscovery {
$allModuleFunctions = & $mut { Get-Command -Module $args[0] -CommandType Function } $script:moduleName

# Build test cases.
$testCases = @()
$testCasesAllModuleFunction = @()

foreach ($function in $allModuleFunctions)
{
$testCases += @{
$testCasesAllModuleFunction += @{
Name = $function.Name
}
}

$allPublicCommand = (Get-Command -Module $script:moduleName).Name

$testCasesPublicCommand = @()

foreach ($command in $allPublicCommand)
{
$testCasesPublicCommand += @{
Name = $command
}
}
}

Describe 'Quality for module' -Tags 'TestQuality' {
Expand All @@ -154,11 +165,11 @@ Describe 'Quality for module' -Tags 'TestQuality' {
}
}

It 'Should have a unit test for <Name>' -ForEach $testCases {
It 'Should have a unit test for <Name>' -ForEach $testCasesAllModuleFunction {
Get-ChildItem -Path 'tests\' -Recurse -Include "$Name.Tests.ps1" | Should -Not -BeNullOrEmpty
}

It 'Should pass Script Analyzer for <Name>' -ForEach $testCases -Skip:(-not $scriptAnalyzerRules) {
It 'Should pass Script Analyzer for <Name>' -ForEach $testCasesAllModuleFunction -Skip:(-not $scriptAnalyzerRules) {
$functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1"

$pssaResult = (Invoke-ScriptAnalyzer -Path $functionFile.FullName)
Expand All @@ -169,88 +180,65 @@ Describe 'Quality for module' -Tags 'TestQuality' {
}

Describe 'Help for module' -Tags 'helpQuality' {
It 'Should have .SYNOPSIS for <Name>' -ForEach $testCases {
$functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1"

$scriptFileRawContent = Get-Content -Raw -Path $functionFile.FullName

$abstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($scriptFileRawContent, [ref] $null, [ref] $null)
Context 'Validating help for <Name>' -ForEach $testCasesAllModuleFunction -Tag 'helpQuality' {
BeforeAll {
$functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1"

$astSearchDelegate = { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }
$scriptFileRawContent = Get-Content -Raw -Path $functionFile.FullName

$parsedFunction = $abstractSyntaxTree.FindAll( $astSearchDelegate, $true ) |
Where-Object -FilterScript {
$_.Name -eq $Name
}
$abstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($scriptFileRawContent, [ref] $null, [ref] $null)

$functionHelp = $parsedFunction.GetHelpContent()

$functionHelp.Synopsis | Should -Not -BeNullOrEmpty
}

It 'Should have a .DESCRIPTION with length greater than 40 characters for <Name>' -ForEach $testCases {
$functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1"

$scriptFileRawContent = Get-Content -Raw -Path $functionFile.FullName

$abstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($scriptFileRawContent, [ref] $null, [ref] $null)

$astSearchDelegate = { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }

$parsedFunction = $abstractSyntaxTree.FindAll($astSearchDelegate, $true) |
Where-Object -FilterScript {
$_.Name -eq $Name
}
$astSearchDelegate = { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }

$functionHelp = $parsedFunction.GetHelpContent()
$parsedFunction = $abstractSyntaxTree.FindAll( $astSearchDelegate, $true ) |
Where-Object -FilterScript {
$_.Name -eq $Name
}

$functionHelp.Description.Length | Should -BeGreaterThan 40
}
$script:functionHelp = $parsedFunction.GetHelpContent()
}

It 'Should have at least one (1) example for <Name>' -ForEach $testCases {
$functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1"
It 'Should have .SYNOPSIS' {
$functionHelp.Synopsis | Should -Not -BeNullOrEmpty
}

$scriptFileRawContent = Get-Content -Raw -Path $functionFile.FullName
It 'Should have a .DESCRIPTION with length greater than 40 characters for <Name>' {
$functionHelp.Description.Length | Should -BeGreaterThan 40
}

$abstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($scriptFileRawContent, [ref] $null, [ref] $null)
It 'Should have at least one (1) example for <Name>' {
$functionHelp.Examples.Count | Should -BeGreaterThan 0
$functionHelp.Examples[0] | Should -Match ([regex]::Escape($function.Name))
$functionHelp.Examples[0].Length | Should -BeGreaterThan ($function.Name.Length + 10)
}

$astSearchDelegate = { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }
It 'Should have described all parameters for <Name>' {
$parameters = $parsedFunction.Body.ParamBlock.Parameters.Name.VariablePath.ForEach({ $_.ToString() })

$parsedFunction = $abstractSyntaxTree.FindAll( $astSearchDelegate, $true ) |
Where-Object -FilterScript {
$_.Name -eq $Name
foreach ($parameter in $parameters)
{
$functionHelp.Parameters.($parameter.ToUpper()) | Should -Not -BeNullOrEmpty -Because ('the parameter {0} must have a description' -f $parameter)
$functionHelp.Parameters.($parameter.ToUpper()).Length | Should -BeGreaterThan 25 -Because ('the parameter {0} must have descriptive description' -f $parameter)
}

$functionHelp = $parsedFunction.GetHelpContent()

$functionHelp.Examples.Count | Should -BeGreaterThan 0
$functionHelp.Examples[0] | Should -Match ([regex]::Escape($function.Name))
$functionHelp.Examples[0].Length | Should -BeGreaterThan ($function.Name.Length + 10)

}
}

It 'Should have described all parameters for <Name>' -ForEach $testCases {
$functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1"

$scriptFileRawContent = Get-Content -Raw -Path $functionFile.FullName

$abstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($scriptFileRawContent, [ref] $null, [ref] $null)

$astSearchDelegate = { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }
It 'Should have a new line at the start of the script file for command <Name>' -ForEach $testCasesPublicCommand {
$publicFunctionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1"

$parsedFunction = $abstractSyntaxTree.FindAll( $astSearchDelegate, $true ) |
Where-Object -FilterScript {
$_.Name -eq $Name
}

$functionHelp = $parsedFunction.GetHelpContent()
$content = Get-Content -Raw -Path $publicFunctionFile.FullName

$parameters = $parsedFunction.Body.ParamBlock.Parameters.Name.VariablePath.ForEach({ $_.ToString() })
$firstLine = $null

foreach ($parameter in $parameters)
{
$functionHelp.Parameters.($parameter.ToUpper()) | Should -Not -BeNullOrEmpty -Because ('the parameter {0} must have a description' -f $parameter)
$functionHelp.Parameters.($parameter.ToUpper()).Length | Should -BeGreaterThan 25 -Because ('the parameter {0} must have descriptive description' -f $parameter)
<#
Singles out the first line of the file. This is so that the test does not
output the entire file but just the first line if the file does not start
with a new line.
#>
if ($content -match '^.*\r?\n') {
$firstLine = $matches[0]
}

$firstLine | Should -Match '^\r?\n' -Because 'due to a bug with ModuleBuilder (see issue https://github.com/PoshCode/ModuleBuilder/issues/126) the first line of the script file must be a new line'
}
}

0 comments on commit b653037

Please sign in to comment.