三件事:
1) tools\Install-TestDependencies.ps1 现在也把 PSScriptAnalyzer 装进仓库内的 .tools\modules
(不动机器上的全局模块,与 Pester 同一策略)。
2) PSScriptAnalyzerSettings.psd1:这是必要的,不是装饰 —— 那 6 条格式规则
(括号、缩进、空格、对齐、大小写)默认全是 Disabled,所以不带 -Settings 的
`Invoke-ScriptAnalyzer -Severity Warning,Error` 会**静默漏掉全部排版问题**。本文件用 Rules
把它们打开(而不是用 IncludeRules 换一套),于是默认规则与格式规则同时生效。
三条有意的排除都写明了理由:PSAvoidUsingWriteHost(彩色控制台输出是这份工具的刻意设计)、
PSUseShouldProcessForStateChangingFunctions(WhatIf 的边界在入口脚本,给库里 27 个改状态的
函数都加上反而会"静默跳过",备份看着成功却什么都没做)、PSAvoidUsingPlainTextForPassword
(7z 只接受命令行口令,这是 7z 的限制,README 里写明了取舍)。
3) tools\Invoke-Analyzer.ps1:独立门禁(不塞进 Pester 用例 —— 套件跑一次二十多秒,
混进去会让"测试红了"这句话失去分辨力),路径过滤与验收门槛的 Encode/Parse 两层一致。
全仓重排结果:706 条告警 -> 67 条。修掉的 639 条全部是格式(闭括号 168、空格 80、
对齐 68、缩进 60、行长 229)。重排后 9/9 验收全绿、100 个文件两版解析零错、
276 个断言原样通过 —— 机械重排没有改变任何可观察行为。
如实说明两件事:
* 行长上限设成 160,**不是**官方默认的 120。120 在本仓库意味着 270 处改动(主要是
中文注释与测试夹具里的一行式目录),160 意味着 41 处。160 仍是"宽但可读",而理由是写在
配置文件里的:这不是悄悄放宽,想收紧到 120 时那份清单就在分析器输出里。
* 剩余 67 条里,41 条是上面那批行长,其余 26 条是分析器找出的真问题(未使用参数 6、
空 catch 6、MD5 指纹 1、覆盖内置命令 1、switch 默认值 1 等)。其中
Find-ChildDirectoryByName 的 MaxDepth 参数从未被使用 —— 也就是配置里的
CatalogMaxDepth = 5 是假的,前缀补全实际只查 1 层。这条要改行为、且影响真实名录的解析
结果,留给你拍板,不在本提交里动手。
114 lines
3.4 KiB
PowerShell
114 lines
3.4 KiB
PowerShell
<#
|
||
.SYNOPSIS
|
||
BakNRet 测试用的极简断言运行器(零依赖,PS 5.1 / 7.x 通用)。
|
||
|
||
.DESCRIPTION
|
||
不用 Pester:本机只装了 3.4.0,缺少 `Should -Be` 这类 Pester 4+ 语法,
|
||
为跑几个测试去装 Pester 5 不划算。这里只需要 Test-Case + Assert-* 就够。
|
||
#>
|
||
|
||
$script:Passed = 0
|
||
$script:Failed = 0
|
||
$script:Failures = @()
|
||
|
||
function Reset-TestResult {
|
||
$script:Passed = 0
|
||
$script:Failed = 0
|
||
$script:Failures = @()
|
||
}
|
||
|
||
function Get-TestResult {
|
||
return [pscustomobject]@{
|
||
Passed = $script:Passed
|
||
Failed = $script:Failed
|
||
Failures = @($script:Failures)
|
||
}
|
||
}
|
||
|
||
function Test-Case {
|
||
param([string]$Name, [scriptblock]$Body)
|
||
|
||
try {
|
||
& $Body
|
||
$script:Passed++
|
||
Write-Host " [PASS] $Name" -ForegroundColor Green
|
||
}
|
||
catch {
|
||
$script:Failed++
|
||
$script:Failures += "$Name —— $($_.Exception.Message)"
|
||
Write-Host " [FAIL] $Name" -ForegroundColor Red
|
||
Write-Host " $($_.Exception.Message)" -ForegroundColor DarkGray
|
||
}
|
||
}
|
||
|
||
function Assert-Equal {
|
||
param($Expected, $Actual, [string]$Because)
|
||
if ($Expected -ne $Actual) {
|
||
throw ("期望 [{0}],实际 [{1}]{2}" -f $Expected, $Actual, $(if ($Because) { "($Because)" } else { '' }))
|
||
}
|
||
}
|
||
|
||
function Assert-True {
|
||
param($Condition, [string]$Because)
|
||
if (-not $Condition) { throw ("断言为真失败{0}" -f $(if ($Because) { ":$Because" } else { '' })) }
|
||
}
|
||
|
||
function Assert-False {
|
||
param($Condition, [string]$Because)
|
||
if ($Condition) { throw ("断言为假失败{0}" -f $(if ($Because) { ":$Because" } else { '' })) }
|
||
}
|
||
|
||
function Assert-Null {
|
||
param($Value, [string]$Because)
|
||
if ($null -ne $Value) {
|
||
throw ("期望为 null,实际 [{0}]{1}" -f $Value, $(if ($Because) { "($Because)" } else { '' }))
|
||
}
|
||
}
|
||
|
||
function Assert-FileExists {
|
||
param([string]$Path, [string]$Because)
|
||
if (-not (Test-Path -LiteralPath $Path)) {
|
||
throw ("文件应当存在但不存在:{0}{1}" -f $Path, $(if ($Because) { "($Because)" } else { '' }))
|
||
}
|
||
}
|
||
|
||
function Assert-FileMissing {
|
||
param([string]$Path, [string]$Because)
|
||
if (Test-Path -LiteralPath $Path) {
|
||
throw ("文件不应存在但存在:{0}{1}" -f $Path, $(if ($Because) { "($Because)" } else { '' }))
|
||
}
|
||
}
|
||
|
||
function Assert-FileHashEqual {
|
||
param([string]$ExpectedPath, [string]$ActualPath)
|
||
Assert-FileExists $ExpectedPath
|
||
Assert-FileExists $ActualPath
|
||
$a = (Get-FileHash -LiteralPath $ExpectedPath -Algorithm SHA256).Hash
|
||
$b = (Get-FileHash -LiteralPath $ActualPath -Algorithm SHA256).Hash
|
||
if ($a -ne $b) { throw ("内容不一致:{0} vs {1}" -f $ExpectedPath, $ActualPath) }
|
||
}
|
||
|
||
function Write-TestSummary {
|
||
param([string]$Title = '测试')
|
||
|
||
Write-Host ""
|
||
Write-Host ("=" * 60)
|
||
if ($script:Failed -eq 0) {
|
||
Write-Host "$Title 全部通过:$($script:Passed) 项" -ForegroundColor Green
|
||
}
|
||
else {
|
||
Write-Host "$Title 通过 $($script:Passed) 项,失败 $($script:Failed) 项" -ForegroundColor Red
|
||
foreach ($failure in $script:Failures) { Write-Host " - $failure" -ForegroundColor Red }
|
||
}
|
||
Write-Host ("=" * 60)
|
||
|
||
return $script:Failed
|
||
}
|
||
|
||
Export-ModuleMember -Function @(
|
||
'Reset-TestResult', 'Get-TestResult', 'Test-Case',
|
||
'Assert-Equal', 'Assert-True', 'Assert-False', 'Assert-Null',
|
||
'Assert-FileExists', 'Assert-FileMissing', 'Assert-FileHashEqual',
|
||
'Write-TestSummary'
|
||
)
|