<# .SYNOPSIS 跑 BakNRet 的 Pester 测试套件(tests/BakNRet.Tests.ps1)。 .DESCRIPTION Pester 从哪儿来,按优先级: 1. 仓库内的 .tools\modules(由 tools/Install-TestDependencies.ps1 放的本地副本,已 gitignore); 2. 机器上已安装的 Pester 5+。 两者都没有时给出一条明确的安装命令并以退出码 2 结束,而不是抛一堆看不懂的错。 为什么显式要求 Pester 5.0+:3.4.0 没有 `Should -Be`,本套件会直接语法错误。 本脚本只把 .tools\modules 临时加进 PSModulePath,**不会**去改机器上的全局模块。 .EXAMPLE pwsh -File .\tests\Run-Pester.ps1 .EXAMPLE pwsh -File .\tests\Run-Pester.ps1 -Verbosity Minimal #> [CmdletBinding()] param( [ValidateSet('Detailed', 'Normal', 'Minimal', 'None')] [string]$Verbosity = 'Detailed', [string[]]$Tag, # 默认跑 tests/ 下所有 *.Tests.ps1(Pester 按这个命名约定发现) [string]$TestPath = $PSScriptRoot ) $ErrorActionPreference = 'Stop' $projectRoot = Split-Path -Parent $PSScriptRoot $localModules = Join-Path $projectRoot '.tools\modules' if (Test-Path -LiteralPath $localModules) { $env:PSModulePath = $localModules + [System.IO.Path]::PathSeparator + $env:PSModulePath } $pester = Get-Module -ListAvailable Pester | Where-Object { [version]$_.Version -ge [version]'5.0.0' } | Sort-Object { [version]$_.Version } -Descending | Select-Object -First 1 if (-not $pester) { $installed = @(Get-Module -ListAvailable Pester | ForEach-Object { $_.Version.ToString() }) Write-Host '' Write-Host '找不到 Pester 5.0+,无法运行 Pester 套件。' -ForegroundColor Red if ($installed.Count -gt 0) { Write-Host ("已安装的版本:{0}(3.x 没有 Should -Be,本套件会语法错误)" -f ($installed -join '、')) -ForegroundColor Yellow } Write-Host '' Write-Host '两种拿到 Pester 5+ 的方式(任选其一):' -ForegroundColor Cyan Write-Host ' A. 只装到仓库里(推荐,不动机器上的全局模块):' -ForegroundColor Cyan Write-Host ' .\tools\Install-TestDependencies.ps1' -ForegroundColor Gray Write-Host ' B. 装到当前用户:' -ForegroundColor Cyan Write-Host ' Install-Module Pester -Scope CurrentUser -MinimumVersion 5.0.0' -ForegroundColor Gray Write-Host '' Write-Host '零依赖的替代方案:.\tests\Run-Tests.ps1(不需要 Pester)' -ForegroundColor Cyan Write-Host '' exit 2 } Import-Module $pester.Path -Force Write-Host ("Pester {0} ({1})" -f $pester.Version, $pester.ModuleBase) -ForegroundColor DarkGray Write-Host ("测试文件:{0}" -f $TestPath) -ForegroundColor DarkGray $configuration = New-PesterConfiguration $configuration.Run.Path = $TestPath $configuration.Run.PassThru = $true $configuration.Run.Exit = $false $configuration.Output.Verbosity = $Verbosity if ($Tag) { $configuration.Filter.Tag = $Tag } # 关掉 Pester 的 TestRegistry:它会去写注册表(HKCU 下的测试键), # 在受限环境 / 沙箱里会被拒绝,于是**所有**容器都以 # "Was not able to registry key for TestRegistry" 失败。 # 本套件不用 TestRegistry(只用临时目录),关掉它不影响任何用例。 $configuration.TestRegistry.Enabled = $false $result = Invoke-Pester -Configuration $configuration # 容器级失败(发现阶段的语法错误、Describe 外的异常)不会进 FailedCount, # 只会在输出里出现一行 "Container failed" —— 不显式检查就会把"根本没跑起来" # 报成"全部通过"。这里把它也当成失败。 $failedContainers = @($result.Containers | Where-Object { $_.Result -eq 'Failed' }) Write-Host '' if ($result.FailedCount -gt 0 -or $failedContainers.Count -gt 0) { Write-Host ("Pester 测试通过 {0} 项,失败 {1} 项,跳过 {2} 项,容器级失败 {3} 个" -f ` $result.PassedCount, $result.FailedCount, $result.SkippedCount, $failedContainers.Count) -ForegroundColor Red foreach ($container in $failedContainers) { Write-Host (" 容器失败:{0}" -f $container.Item) -ForegroundColor Red } exit 1 } Write-Host ("Pester 测试全部通过:{0} 项(跳过 {1} 项)" -f $result.PassedCount, $result.SkippedCount) -ForegroundColor Green exit 0