Invoke-Tests.ps1
|
#!/usr/bin/env pwsh #Requires -Version 7.0 <# .SYNOPSIS CI-ready test runner for KlippyCLI module. .DESCRIPTION Runs Pester tests with configurable options for local development and CI/CD pipelines. Outputs results in multiple formats. .PARAMETER TestType Type of tests to run: Unit, Integration, Lint, or All. Default is Unit. .PARAMETER OutputPath Path for test result files. Default is ./TestResults. .PARAMETER CodeCoverage Enable code coverage reporting. .PARAMETER CI Run in CI mode with NUnit output format. .EXAMPLE ./Invoke-Tests.ps1 Runs unit tests only. .EXAMPLE ./Invoke-Tests.ps1 -TestType All -CodeCoverage Runs all tests with code coverage. .EXAMPLE ./Invoke-Tests.ps1 -TestType Integration Runs integration tests (requires KLIPPY_TEST_PRINTER env var). .EXAMPLE ./Invoke-Tests.ps1 -CI Runs tests in CI mode with NUnit output. #> [CmdletBinding()] param( [Parameter()] [ValidateSet('Unit', 'Integration', 'Lint', 'All')] [string]$TestType = 'Unit', [Parameter()] [string]$OutputPath = './TestResults', [Parameter()] [switch]$CodeCoverage, [Parameter()] [switch]$CI ) $ErrorActionPreference = 'Stop' Set-StrictMode -Version Latest # Ensure output directory exists if (-not (Test-Path $OutputPath)) { New-Item -Path $OutputPath -ItemType Directory -Force | Out-Null } # Check for required modules $requiredModules = @('Pester') if ($TestType -eq 'Lint' -or $TestType -eq 'All') { $requiredModules += 'PSScriptAnalyzer' } foreach ($module in $requiredModules) { if (-not (Get-Module -ListAvailable -Name $module)) { Write-Host "Installing $module module..." -ForegroundColor Yellow Install-Module -Name $module -Force -Scope CurrentUser -SkipPublisherCheck } Import-Module $module -Force } # Build Pester configuration $pesterConfig = [PesterConfiguration]::Default # Test paths based on type $testPaths = switch ($TestType) { 'Unit' { @('./tests/unit', './tests/KlippyCLI.Tests.ps1') } 'Integration' { @('./tests/integration') } 'Lint' { @('./tests/Lint.Tests.ps1') } 'All' { @('./tests') } } $pesterConfig.Run.Path = $testPaths $pesterConfig.Run.Exit = $CI.IsPresent # Tags $includeTags = switch ($TestType) { 'Unit' { 'Unit' } 'Integration' { 'Integration' } 'Lint' { 'Lint' } 'All' { $null } # Run all tags } if ($includeTags) { $pesterConfig.Filter.Tag = @($includeTags) } # Output configuration $pesterConfig.Output.Verbosity = if ($CI) { 'Detailed' } else { 'Normal' } # Test results if ($CI) { $pesterConfig.TestResult.Enabled = $true $pesterConfig.TestResult.OutputPath = Join-Path $OutputPath "TestResults.xml" $pesterConfig.TestResult.OutputFormat = 'NUnitXml' } # Code coverage if ($CodeCoverage) { $pesterConfig.CodeCoverage.Enabled = $true $pesterConfig.CodeCoverage.Path = @('./functions') $pesterConfig.CodeCoverage.OutputPath = Join-Path $OutputPath "Coverage.xml" $pesterConfig.CodeCoverage.OutputFormat = 'JaCoCo' } # Display configuration Write-Host "`n=== KlippyCLI Test Runner ===" -ForegroundColor Cyan Write-Host "Test Type: $TestType" -ForegroundColor White Write-Host "CI Mode: $CI" -ForegroundColor White Write-Host "Code Coverage: $CodeCoverage" -ForegroundColor White Write-Host "Output Path: $OutputPath" -ForegroundColor White if ($TestType -eq 'Integration' -or $TestType -eq 'All') { if ($env:KLIPPY_TEST_PRINTER) { Write-Host "Test Printer: $env:KLIPPY_TEST_PRINTER" -ForegroundColor Green } else { Write-Host "Warning: KLIPPY_TEST_PRINTER not set - integration tests will be skipped" -ForegroundColor Yellow } } Write-Host "`nRunning tests...`n" -ForegroundColor Cyan # Run Pester $result = Invoke-Pester -Configuration $pesterConfig # Summary Write-Host "`n=== Test Summary ===" -ForegroundColor Cyan if ($result) { Write-Host "Passed: $($result.PassedCount)" -ForegroundColor Green Write-Host "Failed: $($result.FailedCount)" -ForegroundColor $(if ($result.FailedCount -gt 0) { 'Red' } else { 'Green' }) Write-Host "Skipped: $($result.SkippedCount)" -ForegroundColor Yellow Write-Host "Total: $($result.TotalCount)" -ForegroundColor White if ($CodeCoverage -and $result.CodeCoverage) { $coverage = [Math]::Round($result.CodeCoverage.CoveragePercent, 2) Write-Host "`nCode Coverage: $coverage%" -ForegroundColor $(if ($coverage -lt 50) { 'Red' } elseif ($coverage -lt 80) { 'Yellow' } else { 'Green' }) } # Exit with appropriate code for CI if ($CI -and $result.FailedCount -gt 0) { exit 1 } } return $result |