From c8bb4a83b5d471a3af3b79dfba68f90d233da10f Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 14 Apr 2024 20:46:02 +0200 Subject: [PATCH 1/4] Check for function tests --- scripts/helpers/Test-PSModule.ps1 | 5 ++- scripts/tests/PSModule/SourceCode.Tests.ps1 | 44 ++++++++++++++++++--- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/scripts/helpers/Test-PSModule.ps1 b/scripts/helpers/Test-PSModule.ps1 index e7f80fd1..449a4930 100644 --- a/scripts/helpers/Test-PSModule.ps1 +++ b/scripts/helpers/Test-PSModule.ps1 @@ -97,8 +97,9 @@ function Test-PSModule { $containerParams = @{ Path = Join-Path -Path $env:GITHUB_ACTION_PATH -ChildPath 'scripts\tests\PSModule\SourceCode.Tests.ps1' Data = @{ - Path = $Path - Verbose = $true + Path = $Path + TestsPath = $moduleTestsPath + Verbose = $true } } Write-Verbose 'ContainerParams:' diff --git a/scripts/tests/PSModule/SourceCode.Tests.ps1 b/scripts/tests/PSModule/SourceCode.Tests.ps1 index fc7ca72f..15f886d8 100644 --- a/scripts/tests/PSModule/SourceCode.Tests.ps1 +++ b/scripts/tests/PSModule/SourceCode.Tests.ps1 @@ -5,7 +5,10 @@ [CmdLetBinding()] Param( [Parameter(Mandatory)] - [string] $Path + [string] $Path, + + [Parameter(Mandatory)] + [string] $TestsPath ) BeforeAll { @@ -51,7 +54,40 @@ Describe 'PSModule - SourceCode tests' { Should -BeNullOrEmpty -Because 'the script files should be called the same as the function they contain' } - # It 'All script files have tests' {} # Look for the folder name in tests called the same as section/folder name of functions + It 'All script files have tests' { + $issues = @('') + + $testFiles = Get-ChildItem -Path $TestsPath -Recurse -File -Filter '*.ps1' + $functionsInTestFiles = $testFiles | ForEach-Object { + $ast = [System.Management.Automation.Language.Parser]::ParseFile($_.FullName, [ref]$null, [ref]$null) + $ast.FindAll( + { + param($node) + $node -is [System.Management.Automation.Language.CommandAst] -and + $node.GetCommandName() -ne $null + }, + $true + ) | ForEach-Object { + $_.GetCommandName() + } | Sort-Object -Unique + } + + Write-Verbose ($functionsInTestFiles -join [Environment]::NewLine | Out-String) -Verbose + + $functionFiles | ForEach-Object { + $filePath = $_.FullName + $fileName = $_.BaseName + $relativePath = $filePath.Replace($Path, '').Trim('\').Trim('/') + $Ast = [System.Management.Automation.Language.Parser]::ParseFile($filePath, [ref]$null, [ref]$null) + $tokens = $Ast.FindAll( { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] } , $true ) + $functionName = $tokens.Name + if ($functionsInTestFiles -notcontains $functionName) { + $issues += " - $relativePath - $functionName" + } + } + $issues -join [Environment]::NewLine | + Should -BeNullOrEmpty -Because 'a test should exist for each of the functions in the module' + } It "Should not contain '-Verbose' unless it is disabled using ':`$false' qualifier after it" { $issues = @('') @@ -143,13 +179,11 @@ Describe 'PSModule - SourceCode tests' { # It 'boolean parameters in CmdletBinding() attribute are written without assignments' {} # I.e. [CmdletBinding(ShouldProcess)] instead of [CmdletBinding(ShouldProcess = $true)] # It 'has [OutputType()] attribute' {} - # It 'has verb 'New','Set','Disable','Enable' etc. and uses "ShoudProcess" in the [CmdletBinding()] attribute' {} } Context 'Parameter design' { # It 'has parameter description for all functions' {} - # It 'has parameter validation for all functions' {} - # It 'parameters have [Parameters()] attribute' {} + # It 'parameters have [Parameter()] attribute' {} # It 'boolean parameters to the [Parameter()] attribute are written without assignments' {} # I.e. [Parameter(Mandatory)] instead of [Parameter(Mandatory = $true)] # It 'datatype for parameters are written on the same line as the parameter name' {} From b9197e998981f3606f1418d48f347777ce3393c2 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 14 Apr 2024 20:52:06 +0200 Subject: [PATCH 2/4] Fix wording --- scripts/tests/PSModule/SourceCode.Tests.ps1 | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/scripts/tests/PSModule/SourceCode.Tests.ps1 b/scripts/tests/PSModule/SourceCode.Tests.ps1 index 15f886d8..f5fe7f70 100644 --- a/scripts/tests/PSModule/SourceCode.Tests.ps1 +++ b/scripts/tests/PSModule/SourceCode.Tests.ps1 @@ -54,7 +54,7 @@ Describe 'PSModule - SourceCode tests' { Should -BeNullOrEmpty -Because 'the script files should be called the same as the function they contain' } - It 'All script files have tests' { + It 'All functions/filters have tests' { $issues = @('') $testFiles = Get-ChildItem -Path $TestsPath -Recurse -File -Filter '*.ps1' @@ -72,11 +72,8 @@ Describe 'PSModule - SourceCode tests' { } | Sort-Object -Unique } - Write-Verbose ($functionsInTestFiles -join [Environment]::NewLine | Out-String) -Verbose - $functionFiles | ForEach-Object { $filePath = $_.FullName - $fileName = $_.BaseName $relativePath = $filePath.Replace($Path, '').Trim('\').Trim('/') $Ast = [System.Management.Automation.Language.Parser]::ParseFile($filePath, [ref]$null, [ref]$null) $tokens = $Ast.FindAll( { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] } , $true ) From 50b27da421c2f5e1743d10afc05a7efa8ab6669f Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 14 Apr 2024 20:54:45 +0200 Subject: [PATCH 3/4] test --- tests/tests/PSModuleTest.Tests.ps1 | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/tests/tests/PSModuleTest.Tests.ps1 b/tests/tests/PSModuleTest.Tests.ps1 index de344a17..2cd1fa5a 100644 --- a/tests/tests/PSModuleTest.Tests.ps1 +++ b/tests/tests/PSModuleTest.Tests.ps1 @@ -1,11 +1,20 @@ -Describe 'PSModuleTest.Tests.ps1' { - It 'Should be able to import the module' { - Import-Module -Name 'PSModuleTest' -Verbose - Get-Module -Name 'PSModuleTest' | Should -Not -BeNullOrEmpty - Write-Verbose (Get-Module -Name 'PSModuleTest' | Out-String) -Verbose +Describe 'Module' { + It 'Function: Get-InternalPSModule' { + Get-InternalPSModule -Name 'World' | Should -Be 'Hello, World!' } - It 'Should be able to call the function' { + It 'Function: Set-InternalPSModule' { + Set-InternalPSModule -Name 'World' | Should -Be 'Hello, World!' + } + It 'Function: Get-PSModuleTest' { + Get-PSModuleTest -Name 'World' | Should -Be 'Hello, World!' + } + It 'Function: New-PSModuleTest' { + New-PSModuleTest -Name 'World' | Should -Be 'Hello, World!' + } + It 'Function: Set-PSModuleTest' { + Set-PSModuleTest -Name 'World' | Should -Be 'Hello, World!' + } + It 'Function: Test-PSModuleTest' { Test-PSModuleTest -Name 'World' | Should -Be 'Hello, World!' - Write-Verbose (Test-PSModuleTest -Name 'World' | Out-String) -Verbose } } From d968cd926e58134b1ee218c4cc47df01511cdb41 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 14 Apr 2024 21:09:04 +0200 Subject: [PATCH 4/4] Only test public files --- scripts/tests/PSModule/SourceCode.Tests.ps1 | 11 +++++++---- tests/tests/PSModuleTest.Tests.ps1 | 6 ------ 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/scripts/tests/PSModule/SourceCode.Tests.ps1 b/scripts/tests/PSModule/SourceCode.Tests.ps1 index f5fe7f70..e9f3e7aa 100644 --- a/scripts/tests/PSModule/SourceCode.Tests.ps1 +++ b/scripts/tests/PSModule/SourceCode.Tests.ps1 @@ -1,6 +1,6 @@ [Diagnostics.CodeAnalysis.SuppressMessageAttribute( - 'PSReviewUnusedParameter', 'Path', - Justification = 'Path is used to specify the path to the module to test.' + 'PSReviewUnusedParameter', '', + Justification = 'Parameters are used in the test.' )] [CmdLetBinding()] Param( @@ -17,8 +17,11 @@ BeforeAll { Where-Object { $_.Name -in 'public', 'private' } | Get-ChildItem -Filter '*.ps1' -File + $publicFunctionFiles = Get-ChildItem -Directory -Path (Join-Path -Path $Path -ChildPath 'public') -File -Filter '*.ps1' + Write-Verbose "Found $($scriptFiles.Count) script files in $Path" Write-Verbose "Found $($functionFiles.Count) function files in $Path" + Write-Verbose "Found $($publicFunctionFiles.Count) public function files in $Path" } Describe 'PSModule - SourceCode tests' { @@ -54,7 +57,7 @@ Describe 'PSModule - SourceCode tests' { Should -BeNullOrEmpty -Because 'the script files should be called the same as the function they contain' } - It 'All functions/filters have tests' { + It 'All public functions/filters have tests' { $issues = @('') $testFiles = Get-ChildItem -Path $TestsPath -Recurse -File -Filter '*.ps1' @@ -72,7 +75,7 @@ Describe 'PSModule - SourceCode tests' { } | Sort-Object -Unique } - $functionFiles | ForEach-Object { + $publicFunctionFiles | ForEach-Object { $filePath = $_.FullName $relativePath = $filePath.Replace($Path, '').Trim('\').Trim('/') $Ast = [System.Management.Automation.Language.Parser]::ParseFile($filePath, [ref]$null, [ref]$null) diff --git a/tests/tests/PSModuleTest.Tests.ps1 b/tests/tests/PSModuleTest.Tests.ps1 index 2cd1fa5a..d329e702 100644 --- a/tests/tests/PSModuleTest.Tests.ps1 +++ b/tests/tests/PSModuleTest.Tests.ps1 @@ -1,10 +1,4 @@ Describe 'Module' { - It 'Function: Get-InternalPSModule' { - Get-InternalPSModule -Name 'World' | Should -Be 'Hello, World!' - } - It 'Function: Set-InternalPSModule' { - Set-InternalPSModule -Name 'World' | Should -Be 'Hello, World!' - } It 'Function: Get-PSModuleTest' { Get-PSModuleTest -Name 'World' | Should -Be 'Hello, World!' }