Files
BakNRet/tests/Run-Pester.ps1
T
Shuery 43fa4e52dd 清单格式:两种写法(软件名 / 手写目录)都支持 :+ 追加与 :- 排除;名录改用对象数组并逐条介绍目录
需求
- 支持两种条目写法:1) 直接写软件名录里的软件名;2) 用户手写目录。
- 两种写法都必须支持追加(:+)与排除(:-)。
- 软件名录要改进:scoop 合并成"一个软件 + 一个目录数组"。
- 运行时要把"分别是哪些目录、每个目录是干什么的、排除/追加的理由"讲清楚。

实现
- 名录(SoftwareCatalog.psd1 / Get-SoftwareCatalog)
  * 一个软件挂多个目录时写成**对象数组**:@{ Path = '...'; Description = '...' };
    也接受纯字符串数组与旧的 @{ Dirs = ... } / @{ Variants = ... }。
  * 目录说明(Description)一路带到运行日志里。
  * "声明了但当前不存在"的目录不再被丢掉:备份跳过,恢复仍然知道它该回到哪个位置。
  * scoop 合并成一个数组条目(%UserProfile%\scoop\persist + %UserProfile%\.config\scoop);
    ScoopApps-persist 保持独立条目 —— 它和前者末级名同为 persist,并进同一个归档会在包里撞名。
- 解析与解析结果(ConvertFrom-BackupListLine / Resolve-BackupEntry)
  * `:+` 以前只对"软件名且能解析出目录"的写法生效,**手写目录的 :+ 会被整段丢掉**;
    现在统一生效,且 :+ 后面写软件名会按名录展开。
  * 行尾 `# 说明` 解析成 Comment,运行时打印。
- 归档与恢复
  * 同一条目里两个同名目录:打包前明确报错(退出码 1),不再静默混成一棵树。
    (7z 命令行没有"入库改名"的能力,归档内顶层名只能是文件系统上的那个名字。)
  * 恢复时每个源只解出**它自己那棵子树**,不会再往别的父目录里复制兄弟目录。
- 可解释性
  * 新增 Write-BackupEntryPlan:打包前打印条目的目录(含来源与介绍)以及排除/追加的出处;
    Restore.ps1 同样打印"哪棵子树还原到哪、会新建还是覆盖"。
- 孤儿归档审计修正:判据只看当前清单,不再把 manifest 的历史记录当成"已知"。
  否则"条目被合并/改名后留下的旧归档"会被历史记录遮住,永远不会报警。

验证
- Pester 84 项、零依赖单元 49 项、端到端 23 项,全部通过。
- 真实机器:合并后的 scoop.7z 233 MB / 29478 项 / 7z t 通过,manifest.roots=[persist|scoop];
  恢复演练 26982/26982 逐字节一致(.ssh、legendary、Aria 同批通过)。
- 迁移提醒:scoop-config.7z 与 scoop-persist.7z 已无清单条目指向,会出现在孤儿审计里;
  确认 scoop.7z 无误后可以自行删除。
2026-09-22 08:18:16 +08:00

87 lines
3.3 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<#
.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 }
$result = Invoke-Pester -Configuration $configuration
Write-Host ''
if ($result.FailedCount -gt 0) {
Write-Host ("Pester 测试通过 {0} 项,失败 {1} 项,跳过 {2} 项" -f $result.PassedCount, $result.FailedCount, $result.SkippedCount) -ForegroundColor Red
exit 1
}
Write-Host ("Pester 测试全部通过:{0} 项(跳过 {1} 项)" -f $result.PassedCount, $result.SkippedCount) -ForegroundColor Green
exit 0