AKPT.Tests.ps1

# ? TITEL UTest AKPT Module
# ? DESCRIPTION
# ? TAGS UTest Pester Module
# ? VERSION 2019.10.19.2100

$ModulePath = Split-Path -Parent $MyInvocation.MyCommand.Path
$ModuleName = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -Replace ".Tests.ps1"
$ModuleManifest = Resolve-Path "$ModulePath\$ModuleName.psd1"

Describe "Module AKPT" -Tag 'Compliance' {

    Context 'Basic Module Testing' {
        $scripts = Get-ChildItem "$ModulePath\Cmdlets" -Include *.ps1, *.psm1, *.psd1 -Recurse -Exclude *.Tests.ps1
        $testCase = $scripts | Foreach-Object {
            @{
                FilePath = $_.FullName
                FileName = $_.Name
            }
        }
        
        It "Script <FileName> should be valid powershell" -TestCases $testCase {
            param( $FilePath, $FileName )

            $FilePath | Should Exist

            $contents = Get-Content -Path $FilePath -ErrorAction Stop
            $errors = $null
            $null = [System.Management.Automation.PSParser]::Tokenize($contents, [ref]$errors)
            $errors.Count | Should Be 0
        }

        It "Modul '$moduleName' problemlos importiert" {
            { Import-Module -Name $ModulePath -Force } | Should Not Throw
        }
        
        It "Module '$moduleName' problemlos entladen" {
            { Remove-Module -Name $ModuleName -Force } | Should Not Throw
        }
    }
    
    Context 'Manifest Testing' {
        
        It 'Valid Module Manifest' {
            {
                $Script:Manifest = Test-ModuleManifest -Path $ModuleManifest -ErrorAction Stop -WarningAction SilentlyContinue
            } | Should Not Throw
        }
        It 'Valid Manifest Name' {
            $Script:Manifest.Name | Should be $ModuleName
        }
        It 'Generic Version Check' {
            $Script:Manifest.Version -as [Version] | Should Not BeNullOrEmpty
        }
        It 'Valid Manifest Description' {
            $Script:Manifest.Description | Should Not BeNullOrEmpty
        }
        It 'Valid Manifest Root Module' {
            $Script:Manifest.RootModule | Should Be "$ModuleName.psm1"
        }
        It 'Valid Manifest GUID' {
            $Script:Manifest.Guid | Should be 'a0937110-6265-4dff-b670-1b319edeebad'
        }
        It 'No Format File' {
            $Script:Manifest.ExportedFormatFiles | Should BeNullOrEmpty
        }
    }

    Context 'ScriptAnalyzer Tests' {
        $testCase = @()
        $testCase = Get-ChildItem -Path $ModulePath -File -Exclude *.Tests.ps1, *.md, *.psd1, *.ps1xml, *.txt -Recurse -Force | 
            Invoke-ScriptAnalyzer -Severity Error, Warning -ExcludeRule PSUseSingularNouns | 
            Foreach-Object {
                @{
                    ScriptName = $_.ScriptName
                    RuleName   = $_.RuleName
                    Message    = $_.Message
                    Line       = $_.Line
                }
            }
        
        It "Alle relevanten Skript-Dateien sind frei von Regelverletzungen" {
            $testCase.Length | Should -Be 0
        }

        if ($testCase.Length -gt 0) {
            It "REGEL-Verletzung: ><RuleName><, für DATEI: ><ScriptName><, MELDUNG: ><Message><, in ZEILE: ><Line><" -TestCases $testCase {
                param(
                    $ScriptName,
                    $RuleName,
                    $Message,
                    $Line
                )
                $ScriptName | Should BeNullOrEmpty
            }
        }
    }

    Import-Module -Name $ModulePath -Force

    Context 'Exported Functions' {

        $ExportedFunctions = (Get-ChildItem -Path "$ModulePath\Cmdlets\*.ps1" -Exclude *.Tests.ps1 | Select-Object -ExpandProperty Name) -replace '\.ps1$'
        $testCase = $ExportedFunctions | Foreach-Object -Process {@{FunctionName = $_}}
        
        It "Function <FunctionName> should be in manifest" -TestCases $testCase {
            param($FunctionName)
            $ManifestFunctions = $Manifest.ExportedFunctions.Keys
            $FunctionName -in $ManifestFunctions | Should Be $true
        }
    
        It 'Richtige Anzahl der exportierten Funktionen im Vergleich zum Manifest' {
            $ExportedCount = Get-Command -Module $ModuleName -CommandType Function | Measure-Object | Select-Object -ExpandProperty Count
            $ManifestCount = $Manifest.ExportedFunctions.Count

            $ExportedCount | Should be $ManifestCount
        }
    
        It 'Proper Number of Functions Exported compared to Files' {
            $ExportedCount = Get-Command -Module $ModuleName -CommandType Function | Where-Object -Property Name -NE "prompt" | Measure-Object | Select-Object -ExpandProperty Count
            $FileCount     = Get-ChildItem -Path "$ModulePath\Cmdlets\*.ps1" -Exclude *.Tests.ps1 | Measure-Object | Select-Object -ExpandProperty Count
    
            $ExportedCount | Should be $FileCount
        }
    }

    Context 'Exported Aliases' {
        It 'Richtige Anzahl der exportierten Aliase im Vergleich zum Manifest' {
            $ExportedCount = Get-Command -Module $ModuleName -CommandType Alias | Measure-Object | Select-Object -ExpandProperty Count
            $ManifestCount = $Manifest.ExportedAliases.Count
    
            $ExportedCount | Should be $ManifestCount
        }
    
        It 'Richtige Anzahl der exportierten Aliase im Vergleich zu den Cmdlet.ps1-Dateien' {
            $AliasCount    = Get-ChildItem -Path "$ModulePath\Cmdlets\*.ps1" -Exclude *.Tests.ps1 | Select-String "New-Alias" | Measure-Object | Select-Object -ExpandProperty Count
            $ManifestCount = $Manifest.ExportedAliases.Count
    
            $AliasCount  | Should be $ManifestCount
        }
    }

    Remove-Module -Name $ModuleName -Force
    Set-Location -Path .\..
}