Skip to content

Commit cef49aa

Browse files
committed
refactor(pwsh): 将覆盖率验证从跨平台测试门禁中分离
- 新增 `pnpm test:pwsh:coverage` 作为显式覆盖率验证入口 - 将 `pnpm test:pwsh:all` 改为使用无覆盖率的 host 断言路径,提升执行速度约12秒 - 保留 `pnpm test:pwsh:full` 作为兼容入口,当前等价于 coverage 命令 - 更新文档、OpenSpec 和 CI 配置以反映新的职责边界 - 修复 Pester 覆盖率目标为 50%,与 OpenSpec 规范对齐 - 优化 benchmark 测试在默认门禁中的输出噪音
1 parent 01f588a commit cef49aa

16 files changed

Lines changed: 684 additions & 70 deletions

File tree

.github/workflows/test.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,16 @@ jobs:
3232
- name: Run Pester
3333
shell: pwsh
3434
run: |
35-
Invoke-Pester -Configuration (./PesterConfiguration.ps1)
35+
$env:PWSH_TEST_MODE = 'full'
36+
if ('${{ matrix.os }}' -eq 'windows-latest') {
37+
$env:PWSH_TEST_ENABLE_COVERAGE = 'true'
38+
}
39+
else {
40+
$env:PWSH_TEST_ENABLE_COVERAGE = 'false'
41+
}
42+
$config = ./PesterConfiguration.ps1
43+
$config.Run.Exit = $true
44+
Invoke-Pester -Configuration $config
3645
3746
# 测试图形化报告
3847
- name: Publish Test Report

.vscode/tasks.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{
55
"label": "Run Tests",
66
"type": "shell",
7-
"command": "Invoke-Pester -Configuration (./PesterConfiguration.ps1)",
7+
"command": "pnpm test:pwsh:coverage",
88
"group": {
99
"kind": "test",
1010
"isDefault": true
@@ -16,4 +16,4 @@
1616
"problemMatcher": []
1717
}
1818
]
19-
}
19+
}

AGENTS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
- 每个代码改动任务完成时,执行根目录 `pnpm qa` 修复出现的问题;如果只修改了文案,不用执行 `qa`
22
- 若改动涉及 pwsh 相关内容(如 `scripts/pwsh/**``profile/**``psutils/**``tests/**/*.ps1``PesterConfiguration.ps1``docker-compose.pester.yml`),提交代码前执行 `pnpm test:pwsh:all`
3-
- 若本机 Docker 不可用,至少执行 `pnpm test:pwsh:full`,并在说明中明确 Linux 覆盖依赖 CI 或 WSL。
3+
- 如需显式验证 coverage 门槛或改动涉及 coverage 规范,额外执行 `pnpm test:pwsh:coverage`
4+
- 若本机 Docker 不可用,至少执行 `pnpm test:pwsh:full`(兼容保留,当前等价 `pnpm test:pwsh:coverage`),并在说明中明确 Linux 覆盖依赖 CI 或 WSL。
45
- 你必须为所有输出的代码补充清晰规范的注释。公共接口标注核心功能、入参、返回值,非直观逻辑补充设计意图,- 不重复代码本身的语义。
56
- 创建skill时使用中文,除了术语等
67

CLAUDE.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,26 @@ pnpm test:pwsh:serial
138138
# Debug output
139139
pnpm test:pwsh:debug
140140

141-
# Full local validation on host
141+
# Explicit host coverage validation
142+
pnpm test:pwsh:coverage
143+
144+
# Full local validation on host (compatibility alias for coverage)
142145
pnpm test:pwsh:full
143146

147+
# Host full assertions without coverage (used by test:pwsh:all)
148+
pnpm test:pwsh:full:assertions
149+
150+
# Slowest files on host assertions path
151+
pnpm test:pwsh:slowest
152+
153+
# Slowest files on explicit coverage path
154+
pnpm test:pwsh:coverage:slowest
155+
144156
# Linux container validation
145157
pnpm test:pwsh:linux:fast
146158
pnpm test:pwsh:linux:full
147159

148-
# Cross-environment pre-commit validation for pwsh-related changes
160+
# Cross-environment pre-commit assertions for pwsh-related changes
149161
pnpm test:pwsh:all
150162

151163
# Profile-specific tests only
@@ -165,7 +177,7 @@ Pester configuration is in `PesterConfiguration.ps1` with environment-driven mod
165177
- Parallelism: 4 threads (disabled in serial mode)
166178
- CI: `$env:CI` controls exit-on-failure and detailed output
167179
- Root `pnpm test:pwsh:*` scripts force `Run.Exit = $true`, so CLI commands return non-zero on failures
168-
- Local coverage responsibility is kept on `pnpm test:pwsh:full`; `pnpm test:pwsh:linux:full` focuses on Linux full assertions to avoid container-specific Pester coverage cleanup failures
180+
- Local coverage responsibility is kept on `pnpm test:pwsh:coverage`; `pnpm test:pwsh:full` is retained as a compatibility alias, `pnpm test:pwsh:full:assertions` is the host lane used by `pnpm test:pwsh:all`, and `pnpm test:pwsh:linux:full` focuses on Linux full assertions to avoid container-specific Pester coverage cleanup failures
169181

170182
### Formatting
171183

@@ -218,7 +230,7 @@ pnpm qa:benchmark
218230

219231
The Turbo pipeline runs: `typecheck:fast -> check -> test:fast` per workspace package.
220232
Set `QA_BASE_REF` to change the diff baseline (default: `origin/master`).
221-
For pwsh-related changes under `scripts/pwsh/**`, `profile/**`, `psutils/**`, `tests/**/*.ps1`, `PesterConfiguration.ps1`, or `docker-compose.pester.yml`, run `pnpm test:pwsh:all` before commit. If Docker is unavailable, run `pnpm test:pwsh:full` and rely on CI or WSL for Linux assertions.
233+
For pwsh-related changes under `scripts/pwsh/**`, `profile/**`, `psutils/**`, `tests/**/*.ps1`, `PesterConfiguration.ps1`, or `docker-compose.pester.yml`, run `pnpm test:pwsh:all` before commit. Run `pnpm test:pwsh:coverage` when you need an explicit local coverage gate. If Docker is unavailable, run `pnpm test:pwsh:full` and rely on CI or WSL for Linux assertions.
222234

223235
### Per-workspace QA commands
224236

PesterConfiguration.ps1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ $config = @{
108108
# “full 断言回归但不承担 coverage”的执行模式。
109109
Enabled = $isCoverageEnabled
110110
Path = "./psutils/modules/*.psm1"
111+
# 显式写回仓库当前采用的 50% 覆盖率门槛,避免继续沿用 Pester 默认 75%
112+
# 导致控制台输出与 OpenSpec 规范长期漂移。
113+
CoveragePercentTarget = 50
111114
# OutputPath = "./coverge.xml"
112115
OutputFormat = 'CoverageGutters'
113116
ExcludeFromCodeCoverage = @(

README.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,9 +343,21 @@ pnpm test:pwsh:slow
343343
# 全量 + 详细输出
344344
pnpm test:pwsh:detailed
345345
346-
# Host 完整测试(含覆盖率与 Profile)
346+
# Host assertions 路径慢测排行(默认不含 coverage)
347+
pnpm test:pwsh:slowest
348+
349+
# 显式 coverage 路径慢测排行
350+
pnpm test:pwsh:coverage:slowest
351+
352+
# 显式 coverage 验证(推荐)
353+
pnpm test:pwsh:coverage
354+
355+
# Host 完整测试(兼容保留,当前等价于 coverage)
347356
pnpm test:pwsh:full
348357
358+
# Host 完整断言(不含 coverage,与 all 的 host 路径一致)
359+
pnpm test:pwsh:full:assertions
360+
349361
# 首次运行前构建 Linux 测试镜像
350362
pnpm test:pwsh:linux:build
351363
@@ -355,15 +367,21 @@ pnpm test:pwsh:linux:fast
355367
# Linux 容器完整测试
356368
pnpm test:pwsh:linux:full
357369
358-
# 提交前并发执行 host + Linux 两套完整测试
370+
# 提交前并发执行 host assertions + Linux full
359371
pnpm test:pwsh:all
360372
```
361373

362374
当前 `pnpm test:pwsh:linux:full` 聚焦 Linux 容器内的 full 断言回归;
363-
本地 coverage 由 `pnpm test:pwsh:full` 提供,以规避容器内 Pester coverage 收尾异常。
375+
默认 `pnpm test:pwsh:all` 改为走 host `pnpm test:pwsh:full:assertions` + Linux `pnpm test:pwsh:linux:full`
376+
以避免把 host coverage 收尾继续留在提交前关键路径里。
377+
378+
本地 coverage 由 `pnpm test:pwsh:coverage` 提供;
379+
`pnpm test:pwsh:full` 当前作为兼容保留入口,等价于 `pnpm test:pwsh:coverage`
380+
以规避容器内 Pester coverage 收尾异常,并避免现有工具链一次性断裂。
364381

365382
`test:pwsh:*` 只负责 root PowerShell / Pester 测试;`qa` / `qa:all` 仍是快速质量门。
366383
若改动涉及 `scripts/pwsh/**``profile/**``psutils/**``tests/**/*.ps1``PesterConfiguration.ps1``docker-compose.pester.yml`,提交前执行 `pnpm test:pwsh:all`
384+
如需显式验证 coverage 门槛,额外执行 `pnpm test:pwsh:coverage`
367385
如果本机 Docker 不可用,至少执行 `pnpm test:pwsh:full`,并依赖 CI 或 WSL 补 Linux 断言验证。
368386

369387
**格式化命令**:

docs/brainstorms/2026-03-15-pwsh-test-log-optimization-brainstorm.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ topic: pwsh-test-log-optimization
2727
- `cache.Tests.ps1` 双平台都在 `5s` 左右,说明这里既有文件 IO,也有 `Start-Sleep` 一类真实时间等待,属于中优先级热点。
2828
- 当前日志共有 `32``What if:`,其中绝大多数来自 `Sync-PathFromBash` 对缓存目录与 PATH 预演的重复提示。额外还有 `3``WARNING:`,来源集中在 `env.Tests.ps1``web.Tests.ps1`
2929
- 一个关键事实是:`WhatIf` 提示不能靠 `6>$null``$WarningPreference='SilentlyContinue'``$InformationPreference='SilentlyContinue'` 静音。也就是说,剩余 `WhatIf` 噪音不是“流重定向还没写够”,而是测试边界本身需要重构。
30+
- 在 2026-03-15 的一轮实测中,当前 `pnpm test:pwsh:all` 外层墙钟约为 `50.62s`;仅通过环境变量关闭 host coverage(Linux 维持现状)后,同等命令下降到 `37.72s`。两组日志里的 `host Tests completed in` 分别约为 `30.59s``31.5s`,说明节省的 `12.9s` 主要不在测试文件本身,而在 host coverage 收尾与结果处理路径。
3031

3132
仓库今天新增的 solution 已经把更早一批热点(例如 `install.Tests.ps1``hardware.Tests.ps1``test.Tests.ps1`)压下去了,所以这次讨论的是“第二梯队剩余空间”,不是重复上一轮工作。
3233

@@ -80,17 +81,19 @@ topic: pwsh-test-log-optimization
8081
**Best when:** 你接受 `full` 只保留稳定、高信号的功能断言,而把性能展示、交互演示型用例下沉到专门入口。
8182

8283
## Recommendation
83-
推荐 **Approach A** 作为主线,但对极少数“明显更像诊断而不是门禁断言”的测试,预留 **Approach C** 的收口空间。
84+
推荐 **Approach A** 作为主线,但对极少数“明显更像诊断而不是门禁断言”的测试,预留 **Approach C** 的收口空间;同时把 host coverage 从默认 `all` 关键路径中拆出,单独提供 `pnpm test:pwsh:coverage`
8485

8586
原因很直接:
8687

8788
- 当前 `test:pwsh:all` 的墙钟时间由 host `39.05s` 和 linux `40.4s` 共同决定,优先打共享热点最有效。
89+
- 仅移除 host coverage 就能让 `pnpm test:pwsh:all` 外层墙钟从 `50.62s` 降到 `37.72s`,这是当前最确定、收益最大的外层优化点。
8890
- `WhatIf` 残余噪音已经证明不能再靠重定向补丁解决,必须从测试设计上收口。
8991
- `WARNING:` 残余只剩少数明确来源,属于低风险、可快速收口的问题。
9092
- 真正可能需要你拍板的,只剩“`help.Tests.ps1` 里的性能对比测试是否继续留在默认 full”这一类边界问题。
9193

9294
## Key Decisions
9395
- 下一轮优化优先级应从“只看 host 热点”改为“优先看双平台共享热点”,否则 `all` 的真实体感时间降不下来。
96+
- 默认 `pnpm test:pwsh:all` 应改为“host 功能断言(不含 coverage)+ linux full”并发门禁;coverage 改由单独的 `pnpm test:pwsh:coverage` 承担。
9497
- `help.Tests.ps1` 是当前第一优先级,因为它同时兼具“单文件极慢”和“更偏诊断型断言”两个特征。
9598
- `Test-HelpSearchPerformance` 不再留在默认 `test:pwsh:full` / `test:pwsh:all` 门禁中,改由 benchmark 入口承接。
9699
- `Invoke-Benchmark.Tests.ps1` 的主要空间不在 Pester 配置,而在测试实现粒度过重;应优先减少重复子进程拉起次数或把非必要端到端路径下沉。
@@ -101,6 +104,8 @@ topic: pwsh-test-log-optimization
101104
## Resolved Questions
102105
- 是否接受把 **明显诊断型** 的测试从默认 `test:pwsh:all` / `full` 门禁中移出,例如 `help.Tests.ps1` 里的性能对比路径,改由 `debug``Slow` 或单独 benchmark 命令承接?
103106
- 接受,但范围先收敛到 `Test-HelpSearchPerformance`,并明确改由 benchmark 入口承接。
107+
- 是否接受把 host coverage 从默认 `pnpm test:pwsh:all` 中拆出,改为单独命令例如 `pnpm test:pwsh:coverage`
108+
- 接受。实测基线显示,当前 `all` 外层墙钟约 `50.62s`;关闭 host coverage 后约 `37.72s`,收益约 `12.9s`,且 `Tests completed in` 基本不变,证明主要节省来自 coverage 收尾路径。
104109

105110
## Open Questions
106111
- 暂无。

docs/local-cross-platform-testing.md

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,20 @@
1717
# 快速模式(无代码覆盖率,适合日常迭代)
1818
pnpm test:pwsh:fast
1919

20-
# 完整模式(含代码覆盖率,适合提交前验证)
20+
# 显式 coverage 模式(推荐)
21+
pnpm test:pwsh:coverage
22+
23+
# 完整模式(兼容保留,当前等价于 coverage)
2124
pnpm test:pwsh:full
25+
26+
# Host 完整断言(不含 coverage,与 all 的 host 路径一致)
27+
pnpm test:pwsh:full:assertions
28+
29+
# Host assertions 路径慢测排行(默认不含 coverage)
30+
pnpm test:pwsh:slowest
31+
32+
# 显式 coverage 路径慢测排行
33+
pnpm test:pwsh:coverage:slowest
2234
```
2335

2436
### Linux 容器测试
@@ -35,21 +47,22 @@ pnpm test:pwsh:linux:full
3547
```
3648

3749
> 当前 `pnpm test:pwsh:linux:full` 聚焦 Linux 容器内的 full 断言回归,不再承担本地 coverage 收尾;
38-
> coverage 责任由 `pnpm test:pwsh:full` 提供,以规避容器内 Pester coverage 收尾异常。
50+
> coverage 责任由 `pnpm test:pwsh:coverage` 提供,`pnpm test:pwsh:full` 作为兼容保留入口等价于该命令,
51+
> 以规避容器内 Pester coverage 收尾异常。
3952
4053
### 完整本地验证(Host + Linux)
4154

4255
推荐直接运行跨环境聚合入口:
4356

4457
```bash
45-
# 并发执行 host full + Linux full
58+
# 并发执行 host assertions-only + Linux full
4659
pnpm test:pwsh:all
4760
```
4861

4962
如需手动串行验证:
5063

5164
```bash
52-
pnpm test:pwsh:full && pnpm test:pwsh:linux:full
65+
pnpm test:pwsh:full:assertions && pnpm test:pwsh:linux:full
5366
```
5467

5568
## Test Modes
@@ -58,10 +71,12 @@ pnpm test:pwsh:full && pnpm test:pwsh:linux:full
5871
|------|------|--------|------|
5972
| `pnpm test:pwsh:fast` | Host || 日常快速迭代 |
6073
| `pnpm test:pwsh:qa` | Host || `qa:pwsh` 使用的快速质量门子集 |
61-
| `pnpm test:pwsh:full` | Host || Host 平台完整验证 |
74+
| `pnpm test:pwsh:coverage` | Host || Host 平台显式 coverage 验证 |
75+
| `pnpm test:pwsh:full` | Host || `coverage` 的兼容保留入口 |
76+
| `pnpm test:pwsh:full:assertions` | Host || Host 平台完整断言,不含 coverage |
6277
| `pnpm test:pwsh:linux:fast` | Linux 容器 || Linux 平台快速验证 |
6378
| `pnpm test:pwsh:linux:full` | Linux 容器 || Linux 平台完整断言验证 |
64-
| `pnpm test:pwsh:all` | Host + Linux 容器 | ✅(由 Host 路径承担) | 提交前跨环境完整验证 |
79+
| `pnpm test:pwsh:all` | Host + Linux 容器 | | 提交前跨环境完整断言验证 |
6580
| `pnpm test:pwsh:serial` | Host || 调试发现阶段挂起 |
6681
| `pnpm test:pwsh:debug` | Host || 详细调试输出 |
6782
| `pnpm test:pwsh:profile` | Host || Profile 专项测试 |
@@ -93,9 +108,9 @@ Host 和容器测试的输出隔离策略:
93108

94109
| 平台 | Host 测试 | 容器测试 | 说明 |
95110
|------|-----------|----------|------|
96-
| Windows | ✅ 全部(含 `windowsOnly`)+ Host coverage | ✅ 通用断言 | Windows 特有测试与 coverage 由 host 路径承担 |
97-
| macOS | ✅ 通用(排除 `windowsOnly`)+ Host coverage | ✅ 通用断言 | 通过容器补 Linux 断言验证 |
98-
| Linux | ✅ 通用(排除 `windowsOnly`)+ Host coverage | ✅ 通用断言 | 容器或直接 host 均可 |
111+
| Windows | ✅ 全部(含 `windowsOnly`)+ `pnpm test:pwsh:coverage` | ✅ 通用断言 | Windows 特有测试与规范化 coverage 由 Windows host 路径承担 |
112+
| macOS | ✅ 通用(排除 `windowsOnly`)+ 可选 host coverage | ✅ 通用断言 | 通过容器补 Linux 断言验证 |
113+
| Linux | ✅ 通用(排除 `windowsOnly`)+ 可选 host coverage | ✅ 通用断言 | 容器或直接 host 均可 |
99114

100115
## Docker Image
101116

@@ -116,11 +131,12 @@ pnpm test:pwsh:linux:build
116131
1. **Host 测试仍然完全可用**:所有 `pnpm test:pwsh:*` 的 host 命令不依赖 Docker
117132
2. **Linux 验证依赖 CI**:跳过 `pnpm test:pwsh:linux:*``pnpm test:pwsh:all`,依赖 GitHub Actions CI 矩阵中的 `ubuntu-latest` 作为 Linux 验证
118133
3. **WSL 备选**(仅 Windows):如果有 WSL2 环境,可以直接在 WSL 中运行 `pnpm test:pwsh:full` 作为 Linux 验证的替代方案
134+
4. **如需显式 coverage 门槛验证**:额外执行 `pnpm test:pwsh:coverage`
119135

120136
**判断 Docker 是否可用**
121137

122138
```bash
123139
docker info > /dev/null 2>&1 && echo "Docker OK" || echo "Docker unavailable"
124140
```
125141

126-
> **建议**:如果改动涉及 `scripts/pwsh/**``profile/**``psutils/**``tests/**/*.ps1``PesterConfiguration.ps1``docker-compose.pester.yml`,提交前优先运行 `pnpm test:pwsh:all`。若 Docker 不可用,至少执行 `pnpm test:pwsh:full`,并依赖 CI 或 WSL 补 Linux 断言验证。
142+
> **建议**:如果改动涉及 `scripts/pwsh/**``profile/**``psutils/**``tests/**/*.ps1``PesterConfiguration.ps1``docker-compose.pester.yml`,提交前优先运行 `pnpm test:pwsh:all`若需要显式 coverage 门槛验证,再补 `pnpm test:pwsh:coverage`若 Docker 不可用,至少执行 `pnpm test:pwsh:full`,并依赖 CI 或 WSL 补 Linux 断言验证。

0 commit comments

Comments
 (0)