@chenguangyao/devflow-kit 0.1.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/CHANGELOG.md +232 -0
  2. package/LICENSE +21 -0
  3. package/README.md +539 -0
  4. package/bin/devflow.js +9 -0
  5. package/docs/RFC-001-devflow-kit.md +617 -0
  6. package/docs/RFC-002-workflow-kernel.md +134 -0
  7. package/docs/enterprise-integration-supplement.md +274 -0
  8. package/docs/internal-gitlab-setup.md +426 -0
  9. package/docs/marketplace-skills.md +231 -0
  10. package/docs/migration-from-arb.md +232 -0
  11. package/docs/tooling-overview.md +774 -0
  12. package/docs/workflow-orchestration.md +695 -0
  13. package/docs/workflow-ui-prototype.html +271 -0
  14. package/package.json +52 -0
  15. package/schemas/config.schema.json +51 -0
  16. package/schemas/delta.schema.json +22 -0
  17. package/schemas/state.schema.json +130 -0
  18. package/schemas/status-surface.schema.json +197 -0
  19. package/schemas/workflow-confirmation-surface.schema.json +70 -0
  20. package/schemas/workflow-picker.schema.json +94 -0
  21. package/scripts/postinstall.js +101 -0
  22. package/scripts/render-workflow-ui-prototype.js +271 -0
  23. package/skills/apply/SKILL.md +313 -0
  24. package/skills/apply/references/discipline-checklist.md +145 -0
  25. package/skills/apply/references/subagent-implementer-prompt.md +113 -0
  26. package/skills/apply/references/subagent-orchestration.md +150 -0
  27. package/skills/apply/references/subagent-reviewer-prompt.md +180 -0
  28. package/skills/apply/references/tdd-loop.md +287 -0
  29. package/skills/apply/references/when-plan-is-wrong.md +279 -0
  30. package/skills/apply/references/worktree-swarm.md +292 -0
  31. package/skills/archive/SKILL.md +229 -0
  32. package/skills/archive/references/conflict-resolution.md +336 -0
  33. package/skills/archive/references/knowledge-deposit.md +381 -0
  34. package/skills/archive/references/spec-merge.md +365 -0
  35. package/skills/brainstorm/SKILL.md +123 -0
  36. package/skills/brainstorm/references/proposal-template.md +244 -0
  37. package/skills/brainstorm/references/question-catalog.md +168 -0
  38. package/skills/brainstorm/references/session-template.md +184 -0
  39. package/skills/ci-fix/SKILL.md +63 -0
  40. package/skills/ci-fix/references/loop.md +25 -0
  41. package/skills/code-review/SKILL.md +279 -0
  42. package/skills/code-review/references/escalation-playbook.md +192 -0
  43. package/skills/code-review/references/language-cheatsheets/go.md +175 -0
  44. package/skills/code-review/references/language-cheatsheets/java-spring-mybatis.md +246 -0
  45. package/skills/code-review/references/language-cheatsheets/python.md +170 -0
  46. package/skills/code-review/references/language-cheatsheets/vue.md +199 -0
  47. package/skills/code-review/references/output-template.md +275 -0
  48. package/skills/code-review/references/review-checklist.md +251 -0
  49. package/skills/complexity-grading/SKILL.md +259 -0
  50. package/skills/deliver/SKILL.md +271 -0
  51. package/skills/deliver/references/delivery-modes.md +299 -0
  52. package/skills/deliver/references/notify.md +359 -0
  53. package/skills/deliver/references/pr-description.md +319 -0
  54. package/skills/dependency-upgrade/SKILL.md +57 -0
  55. package/skills/dependency-upgrade/references/risk-matrix.md +38 -0
  56. package/skills/df-orchestrator/SKILL.md +407 -0
  57. package/skills/df-orchestrator/references/complexity-grading.md +177 -0
  58. package/skills/df-orchestrator/references/escalation-matrix.md +191 -0
  59. package/skills/df-orchestrator/references/routing-rules.md +290 -0
  60. package/skills/df-orchestrator/references/workflow-state-machine.md +208 -0
  61. package/skills/frontend-quality/SKILL.md +61 -0
  62. package/skills/frontend-quality/references/checklist.md +35 -0
  63. package/skills/handoff-resume/SKILL.md +59 -0
  64. package/skills/handoff-resume/references/handoff-template.md +54 -0
  65. package/skills/plan/SKILL.md +166 -0
  66. package/skills/plan/references/task-breakdown.md +207 -0
  67. package/skills/plan/references/task-sequencing.md +143 -0
  68. package/skills/plan/references/task-template.md +248 -0
  69. package/skills/requirement-analysis/SKILL.md +499 -0
  70. package/skills/requirement-analysis/references/acceptance-criteria.md +183 -0
  71. package/skills/requirement-analysis/references/code-recon.md +151 -0
  72. package/skills/requirement-analysis/references/edge-case-catalog.md +164 -0
  73. package/skills/requirement-analysis/references/requirement-template.md +339 -0
  74. package/skills/requirement-analysis/references/scope-negotiation.md +162 -0
  75. package/skills/security-hardening/SKILL.md +60 -0
  76. package/skills/security-hardening/references/checklist.md +42 -0
  77. package/skills/tech-spec/SKILL.md +388 -0
  78. package/skills/tech-spec/references/api-contract-design.md +172 -0
  79. package/skills/tech-spec/references/decision-records.md +110 -0
  80. package/skills/tech-spec/references/design-template.md +301 -0
  81. package/skills/tech-spec/references/rollout-and-rollback.md +203 -0
  82. package/skills/tech-spec/references/spec-delta-conventions.md +250 -0
  83. package/skills/tech-spec/references/transaction-patterns.md +212 -0
  84. package/skills/test-spec/SKILL.md +219 -0
  85. package/skills/test-spec/references/coverage-strategy.md +218 -0
  86. package/skills/test-spec/references/edge-case-to-test.md +143 -0
  87. package/skills/test-spec/references/test-case-template.md +276 -0
  88. package/skills/verify/SKILL.md +232 -0
  89. package/skills/verify/references/nfr-verification.md +292 -0
  90. package/skills/verify/references/report-templates.md +510 -0
  91. package/skills/verify/references/self-test-guide.md +240 -0
  92. package/skills/verify/references/verify-rollback-map.md +247 -0
  93. package/src/cli/commands/_helpers.js +108 -0
  94. package/src/cli/commands/_submit.js +718 -0
  95. package/src/cli/commands/apply.js +198 -0
  96. package/src/cli/commands/archive.js +180 -0
  97. package/src/cli/commands/checkpoint.js +113 -0
  98. package/src/cli/commands/deliver.js +377 -0
  99. package/src/cli/commands/deploy.js +504 -0
  100. package/src/cli/commands/design.js +158 -0
  101. package/src/cli/commands/disable.js +21 -0
  102. package/src/cli/commands/doctor.js +178 -0
  103. package/src/cli/commands/enable.js +21 -0
  104. package/src/cli/commands/flow.js +645 -0
  105. package/src/cli/commands/help.js +93 -0
  106. package/src/cli/commands/ingest.js +602 -0
  107. package/src/cli/commands/init.js +341 -0
  108. package/src/cli/commands/knowledge.js +523 -0
  109. package/src/cli/commands/logs.js +43 -0
  110. package/src/cli/commands/new.js +202 -0
  111. package/src/cli/commands/plan.js +49 -0
  112. package/src/cli/commands/propose.js +27 -0
  113. package/src/cli/commands/provider.js +698 -0
  114. package/src/cli/commands/report.js +143 -0
  115. package/src/cli/commands/requirement.js +227 -0
  116. package/src/cli/commands/review.js +301 -0
  117. package/src/cli/commands/skills.js +457 -0
  118. package/src/cli/commands/status.js +925 -0
  119. package/src/cli/commands/switch.js +27 -0
  120. package/src/cli/commands/sync.js +47 -0
  121. package/src/cli/commands/test.js +366 -0
  122. package/src/cli/commands/uninstall.js +32 -0
  123. package/src/cli/commands/update.js +74 -0
  124. package/src/cli/commands/verify.js +354 -0
  125. package/src/cli/commands/worktree.js +78 -0
  126. package/src/cli/index.js +72 -0
  127. package/src/cli/parse-args.js +102 -0
  128. package/src/core/autodetect.js +271 -0
  129. package/src/core/change.js +208 -0
  130. package/src/core/checkpoint.js +217 -0
  131. package/src/core/config.js +60 -0
  132. package/src/core/delta.js +290 -0
  133. package/src/core/markers.js +59 -0
  134. package/src/core/paths.js +173 -0
  135. package/src/core/plan-tasks.js +36 -0
  136. package/src/core/project-routing.js +285 -0
  137. package/src/core/projects.js +200 -0
  138. package/src/core/state.js +200 -0
  139. package/src/core/workflow-check.js +177 -0
  140. package/src/core/workflow-init.js +34 -0
  141. package/src/core/workflow-picker.js +154 -0
  142. package/src/core/workflow-policy.js +119 -0
  143. package/src/core/workflow-suggest.js +181 -0
  144. package/src/core/workflow-verify.js +88 -0
  145. package/src/core/workflow.js +433 -0
  146. package/src/core/worktree.js +241 -0
  147. package/src/knowledge/categories.js +107 -0
  148. package/src/knowledge/classify.js +125 -0
  149. package/src/knowledge/deposit.js +414 -0
  150. package/src/knowledge/migrate.js +149 -0
  151. package/src/knowledge/mr.js +219 -0
  152. package/src/knowledge/query.js +131 -0
  153. package/src/knowledge/registry.js +151 -0
  154. package/src/knowledge/sync.js +179 -0
  155. package/src/providers/base.js +74 -0
  156. package/src/providers/drivers/api-yapi.js +78 -0
  157. package/src/providers/drivers/ci-jenkins.js +109 -0
  158. package/src/providers/drivers/intake-confluence.js +544 -0
  159. package/src/providers/drivers/kb-git.js +549 -0
  160. package/src/providers/drivers/kb-weknora.js +472 -0
  161. package/src/providers/drivers/notify-smtp.js +515 -0
  162. package/src/providers/drivers/observability-oss.js +43 -0
  163. package/src/providers/drivers/observability-sls.js +50 -0
  164. package/src/providers/lifecycle.js +135 -0
  165. package/src/providers/loader.js +132 -0
  166. package/src/providers/local.js +190 -0
  167. package/src/providers/userconfig.js +283 -0
  168. package/src/reports/aggregate.js +185 -0
  169. package/src/reports/coverage.js +163 -0
  170. package/src/reports/detect.js +143 -0
  171. package/src/reports/parse.js +236 -0
  172. package/src/templates/files/ci/github.yml +38 -0
  173. package/src/templates/files/ci/gitlab.yml +27 -0
  174. package/src/templates/files/design.md +63 -0
  175. package/src/templates/files/ide/devflow-workflow.md +58 -0
  176. package/src/templates/files/ide/project-overview-reference.md +1 -0
  177. package/src/templates/files/ide/project-overview.md +27 -0
  178. package/src/templates/files/knowledge-index.json +17 -0
  179. package/src/templates/files/knowledge.md +28 -0
  180. package/src/templates/files/meta.json +8 -0
  181. package/src/templates/files/plan.md +38 -0
  182. package/src/templates/files/proposal.md +33 -0
  183. package/src/templates/files/reports/contract-test.md +40 -0
  184. package/src/templates/files/reports/e2e-test.md +30 -0
  185. package/src/templates/files/reports/integration-test.md +36 -0
  186. package/src/templates/files/reports/joint-test.md +58 -0
  187. package/src/templates/files/reports/perf.md +24 -0
  188. package/src/templates/files/reports/regression.md +20 -0
  189. package/src/templates/files/reports/remote-test.md +55 -0
  190. package/src/templates/files/reports/self-test.md +43 -0
  191. package/src/templates/files/reports/smoke-test.md +22 -0
  192. package/src/templates/files/reports/unit-test.md +36 -0
  193. package/src/templates/files/requirement.md +51 -0
  194. package/src/templates/files/review.md +38 -0
  195. package/src/templates/files/tests.md +36 -0
  196. package/src/templates/files/verify.md +32 -0
  197. package/src/templates/index.js +21 -0
  198. package/src/utils/log.js +37 -0
@@ -0,0 +1,219 @@
1
+ ---
2
+ name: devflow-test-spec
3
+ description: |
4
+ devflow-kit test-spec 阶段基于 `requirement.md`(F-ID + AC)和 `design.md`(改动点 / 契约 / 异常路径)产出
5
+ `tests.md` —— 独立于代码的测试用例清单。下游 `plan.md` 把这些用例映射到 TDD 任务
6
+ (写失败测试 → 实现通过)。触发时机:`devflow design --with-tests` 或 `/df:test-spec`。
7
+ L1/L2 可把测试写进 plan.md,不强制单独出 tests.md;L3 或复杂跨系统验收建议单独生成。
8
+ when_to_use: |
9
+ tech-spec 完成后、plan 之前,且用户/方案明确需要独立测试用例文档时。test-spec 不写具体测试代码,只写"要测什么 + 前置 / 步骤 /
10
+ 期望 + 对应 F-ID"。
11
+ ---
12
+
13
+ # test-spec
14
+
15
+ test-spec 的目的是**把测试的意图从代码实现中分离出来**。意图稳定,实现可以换(框架 / 语言 / 断言风格),只要用例还在就不会漏测。
16
+
17
+ ## 前置检查
18
+
19
+ | 输入 | 必需 | 缺失时 |
20
+ | --- | --- | --- |
21
+ | `requirement.md`(有 F-ID + AC) | 是 | 回退到 requirement-analysis |
22
+ | `design.md`(§5 契约、§7 关键流程、§8 异常处理) | 是 | 回退到 tech-spec |
23
+ | `state.level` | 是 | 用于决定最小覆盖要求 |
24
+
25
+ ## 产物
26
+
27
+ `devflow/changes/<slug>/tests.md`,含:
28
+
29
+ | # | Section | 必选 |
30
+ | --- | --- | --- |
31
+ | 1 | 测试策略(金字塔比例、工具) | 是 |
32
+ | 2 | 数据准备(fixtures、种子) | 是 |
33
+ | 3 | 环境依赖(mock 哪些、stub 哪些) | 是 |
34
+ | 4 | 测试用例索引表(TC-001..) | 是 |
35
+ | 5 | 逐用例详表(type / pre / steps / expected / F-ID) | 是 |
36
+ | 6 | 非功能测试(perf / security 若适用) | L2/L3 |
37
+ | 7 | 回归清单(本次变更可能影响的已有用例) | L2/L3 |
38
+
39
+ 完整模板 + 用例详表字段、正反例见 [`references/test-case-template.md`](references/test-case-template.md)。
40
+
41
+ ## 产物格式规范(对齐 arb 测试用例.md)
42
+
43
+ ```markdown
44
+ # 测试用例:<标题>
45
+
46
+ > JIRA/URL: <引用>
47
+
48
+ ---
49
+
50
+ ## TC-F1:<F1 功能名>
51
+
52
+ | 编号 | 场景 | 前置条件 | 操作 | 预期结果 |
53
+ |------|------|---------|------|---------|
54
+ | TC-F1-01 | 正向:<场景描述> | <系统状态 + 数据> | <HTTP 方法 + 路径 + 参数> | <状态码 + body 断言> |
55
+ | TC-F1-02 | 边界:<场景描述> | ... | ... | ... |
56
+ | TC-F1-03 | 异常:<场景描述> | ... | ... | ... |
57
+
58
+ ---
59
+
60
+ ## TC-F2:<F2 功能名>
61
+
62
+ | 编号 | 场景 | 前置条件 | 操作 | 预期结果 |
63
+ |------|------|---------|------|---------|
64
+ | TC-F2-01 | ... | ... | ... | ... |
65
+
66
+ ---
67
+
68
+ ## TC-C1:<C1 技术变更(如无对应 F-ID 的底层变更)>
69
+
70
+ | 编号 | 场景 | 前置条件 | 操作 | 预期结果 |
71
+ |------|------|---------|------|---------|
72
+ | TC-C1-01 | ... | ... | ... | ... |
73
+ ```
74
+
75
+ **格式说明:**
76
+ - 按 **F-ID 分节**(每个功能点一个 `## TC-F{n}` 节),而不是全局顺序编号
77
+ - 编号格式:`TC-F{功能号}-{序号}`(如 `TC-F2-01`);纯技术变更用 `TC-C{号}-{序号}`
78
+ - 表格列:**编号 | 场景 | 前置条件 | 操作 | 预期结果** — 每行一个用例,紧凑可读
79
+ - 每个 F-ID 节至少 3 行:正向 / 边界 / 异常(L2/L3 要求)
80
+
81
+ ## 用例编号与映射
82
+
83
+ - 编号按功能分节:`TC-F{n}-{seq}`(如 `TC-F2-01`,F 对应 requirement 的 F-ID)
84
+ - 每个 TC 必须能对应到 design.md 的一条流程(happy 或 failure path)
85
+ - 若测非功能需求,用 `TC-NFR-{domain}-{seq}`(如 `TC-NFR-perf-01`)
86
+
87
+ **硬闸**:F-ID 未覆盖的 → test-spec 回退 requirement / design 看是不是少写了 AC
88
+
89
+ ## 测试金字塔(强制分层)
90
+
91
+ ```
92
+ /\
93
+ / \ e2e 5% (少量,纯粹端到端)
94
+ /----\
95
+ / \ integration 20-30% (服务与 DB / 外部系统)
96
+ /--------\
97
+ / \ unit 65-75% (纯函数 / 单类,快、确定、无 IO)
98
+ /------------\
99
+ ```
100
+
101
+ **原则**:
102
+
103
+ - **Unit** 是主战场,覆盖业务逻辑分支
104
+ - **Integration** 覆盖"代码 + 依赖"一层(DB / MQ / 外部 API mock)
105
+ - **e2e** 保留最关键的用户场景,不求 coverage;慢、脆、贵
106
+
107
+ 按层的覆盖策略见 [`references/coverage-strategy.md`](references/coverage-strategy.md)。
108
+
109
+ ## F-ID → TC 的映射规则
110
+
111
+ | 每个 F-ID 至少覆盖 | L1 | L2 | L3 |
112
+ | --- | --- | --- | --- |
113
+ | 1 个正向 TC | ✓ | ✓ | ✓ |
114
+ | 1 个边界 TC(引用 requirement.md §8 的一行) | — | ✓ | ✓ |
115
+ | 1 个异常 TC(引用 design.md §8 一个错误路径) | — | ✓ | ✓ |
116
+ | 1 个性能 / 可观测性 TC(NFR) | — | — | ✓ |
117
+
118
+ 若一个 F-ID 无法满足 ≥ 2 个 TC(L2/L3),说明 AC 写得太粗,回退 requirement 拆。
119
+
120
+ F-ID → TC 映射完整决策树与例子库见 [`references/edge-case-to-test.md`](references/edge-case-to-test.md)。
121
+
122
+ ## 每个用例要包含什么
123
+
124
+ ```
125
+ TC-001
126
+ type: unit | integration | e2e
127
+ linkedF: F-01 (+ 可多个)
128
+ priority: P0 | P1 | P2 (P0 = 必过;P1 = 应过;P2 = 最好过)
129
+ preconditions: <fixture / 系统状态>
130
+ steps: 1. ... 2. ... 3. ...
131
+ expected: <可自动化断言的期望>
132
+ dataSource: <fixture 文件或数据生成规则>
133
+ notes: <如 flaky / skip 原因>
134
+ ```
135
+
136
+ **关键**:每个字段都要能**机器解析**。step 和 expected 用编号列表 + 断言级别描述,不要用散文。
137
+
138
+ ## 不写具体代码
139
+
140
+ test-spec 是**意图文档**,不是"单测代码草稿"。不要出现:
141
+
142
+ - `assertEquals(...)` / `expect(...).toBe(...)` 这种具体框架语法
143
+ - `new UserMapper()` 这种具体类名(除非用例要求验证该类)
144
+ - 具体参数结构(参数结构由 design.md §5 契约规定)
145
+
146
+ 正确:`expected: 响应 200, body.grantedCount === 990, body.failedUsers.length === 10`。
147
+
148
+ ## 测试数据(§2)
149
+
150
+ 统一安排 fixture,而不是散在各用例里。常见来源:
151
+
152
+ | 来源 | 适用 |
153
+ | --- | --- |
154
+ | 固定 json/yaml fixture 文件 | 多 case 共享、schema 稳定 |
155
+ | Factory 工厂 | 需要少量差异、可组合 |
156
+ | 随机 / 属性测试 | 幂等 / 纯函数 / 边界扫描 |
157
+ | 生产导出样本(脱敏) | 真实 workload 回归 |
158
+
159
+ 数据准备原则:**不能依赖执行顺序、不能污染别的 case**(每 case 要能独立跑、可重复)。
160
+
161
+ ## 非功能测试(§6,L3 必有)
162
+
163
+ | 域 | 测什么 | 工具 |
164
+ | --- | --- | --- |
165
+ | Performance | 接口延迟 / 吞吐;对照基线 | JMeter / k6 / Gatling / wrk |
166
+ | Security | 鉴权 / 越权 / 敏感数据泄漏 | 漏扫 / 手工 / OWASP ZAP |
167
+ | Reliability | 故障注入 / 降级 | Chaos / toxy-proxy |
168
+ | Observability | 指标 / 日志 / traceId 透传 | 观测断言 |
169
+
170
+ 非功能 TC 也要有编号,如 `NFR-PERF-001`。
171
+
172
+ ## 硬闸(Done Criteria)
173
+
174
+ 进入 `devflow plan` 前:
175
+
176
+ - [ ] 每个 F-ID 至少有对应的 TC(数量达到 level 要求)
177
+ - [ ] 每个"对外契约变更"有 contract / integration TC
178
+ - [ ] 每个"契约消费者影响矩阵"条目都有 consumer / frontend / e2e 或 integration TC,覆盖无参数回跳、老链接兼容、轮询 key 来源、页面刷新 / 直达等场景
179
+ - [ ] 每条 design.md §8 的 failure path 有对应 negative TC
180
+ - [ ] §2 数据准备 / §3 环境依赖写了(不能"apply 时再说")
181
+ - [ ] L3:有至少 1 个 perf TC
182
+
183
+ 未达标 → 继续写;都达标 → DONE → `devflow plan`。
184
+
185
+ ## 反模式
186
+
187
+ - **只测 happy path**:边界和异常的 bug 占 bug 池的 60%+。少写 = 交付后补 bug。
188
+ - **"断言不抛异常"**:assertDoesNotThrow 是零信息断言。改写具体期望(业务字段 / 响应状态 / 副作用)。
189
+ - **一个用例断言一大堆**:一个 TC 断言 ≤ 5 条;超过拆。
190
+ - **TC 没有 F-ID**:无法验证覆盖率,下游 review 时无法追溯。
191
+ - **测试数据用生产环境真实数据**(含 PII):合规违规;用脱敏或 factory。
192
+ - **依赖执行顺序**:TC-002 必须在 TC-001 后跑 → case 间无关性丧失。
193
+ - **把具体实现类名写进 tests.md**:实现改了测试意图文档也要改,耦合。
194
+ - **把测试框架语法塞进 tests.md**:tests.md 应是语言无关的,切框架不要动它。
195
+ - **不考虑并发 / 重复调用**:特别是幂等接口。
196
+ - **忽略 L3 的 perf TC**:L3 没 perf 等于裸奔。
197
+
198
+ ## 完成状态协议
199
+
200
+ ```
201
+ ---STATUS---
202
+ result: DONE | DONE_WITH_CONCERNS | BLOCKED | NEEDS_INPUT
203
+ outputs:
204
+ - devflow/changes/<slug>/tests.md
205
+ testCaseCount:
206
+ unit: N1
207
+ integration: N2
208
+ e2e: N3
209
+ nfr: N4
210
+ fIdCoverage: K/K # K 个 F-ID 中全部覆盖
211
+ nextAction: devflow plan
212
+ ---END_STATUS---
213
+ ```
214
+
215
+ ## 参考
216
+
217
+ - [`references/test-case-template.md`](references/test-case-template.md) — tests.md 完整模板 + 用例详表字段 + 正反例 + L2 完整示例
218
+ - [`references/coverage-strategy.md`](references/coverage-strategy.md) — 金字塔分层的具体分配、分层时机、覆盖率目标、什么不值得测
219
+ - [`references/edge-case-to-test.md`](references/edge-case-to-test.md) — requirement §8 边界场景 → TC 的映射决策树 + 例子库
@@ -0,0 +1,218 @@
1
+ # test-spec / coverage-strategy
2
+
3
+ 测试金字塔的分层原则、每层覆盖什么、覆盖率目标、什么不值得测。
4
+
5
+ ---
6
+
7
+ ## 金字塔原则(再一次强调)
8
+
9
+ ```
10
+ /\ e2e 5% 昂贵、脆弱、慢。覆盖最关键用户路径
11
+ / \
12
+ ----
13
+ \ integration 20-30% 代码 + 依赖(DB/MQ/mock 外部 API)
14
+ ------
15
+ \ unit 65-75% 纯逻辑、分支覆盖主战场
16
+ ----------
17
+ ```
18
+
19
+ **错误分布**(工业经验):
20
+
21
+ - 60-70% 的 bug 可以用 unit 覆盖
22
+ - 20-25% 需要 integration
23
+ - 5-10% 需要 e2e
24
+
25
+ **预算分布**:
26
+
27
+ - 80% 测试时间应花在 unit(写得快、跑得快、修得快)
28
+ - 15% 在 integration
29
+ - 5% 在 e2e
30
+
31
+ ---
32
+
33
+ ## 每层测什么
34
+
35
+ ### Unit 层
36
+
37
+ **测**:
38
+
39
+ - 纯函数(输入 → 输出),所有分支
40
+ - 单类(controller / service / mapper 单独实例化,依赖全 mock)
41
+ - 边界 / 异常 / 极值 / 幂等
42
+ - 工具类、helper、validator
43
+
44
+ **不测**:
45
+
46
+ - 实际 DB 访问(那是 integration)
47
+ - 外部 HTTP 调用(那是 integration)
48
+ - UI 交互 / e2e 流程
49
+
50
+ **对象 / 依赖处理**:
51
+
52
+ - 依赖全部 mock / stub(显式声明行为)
53
+ - 不用真实 Spring context;用构造注入 + mock
54
+ - 单个 test < 100ms
55
+
56
+ ---
57
+
58
+ ### Integration 层
59
+
60
+ **测**:
61
+
62
+ - 服务 + DB:SQL 正确、约束生效、事务边界、索引起作用
63
+ - 服务 + MQ:消息生产 / 消费、重试、死信
64
+ - 服务 + 外部 API:mock 服务器模拟成功 / 失败 / 超时
65
+ - 整条 Controller → Service → Repository 链路
66
+
67
+ **工具**:
68
+
69
+ | 语言 | 工具 |
70
+ | --- | --- |
71
+ | Java | Spring Boot Test、@SpringBootTest + Testcontainers MySQL |
72
+ | Go | testify + dockertest / testcontainers-go |
73
+ | Python | pytest + pytest-docker |
74
+ | Node | supertest + testcontainers-node |
75
+
76
+ **不测**:
77
+
78
+ - 跨服务(那是 e2e)
79
+ - UI(那是 e2e)
80
+
81
+ ---
82
+
83
+ ### E2E 层
84
+
85
+ **测**(少量,慎选):
86
+
87
+ - 核心用户路径("下单 → 支付 → 到货")
88
+ - 关键冒烟场景("启动服务能访问首页")
89
+ - 跨服务关键交互("下单扣库存扣余额" 端到端)
90
+
91
+ **不测**:
92
+
93
+ - 所有 F-ID(那是 unit/integration 的工作)
94
+ - 大多数边界 / 异常(太慢太脆)
95
+ - 性能(那是 perf 独立层)
96
+
97
+ **设计原则**:
98
+
99
+ - 每个 e2e < 30 秒;超过要审视
100
+ - 尽量少 mock,尽量真实环境
101
+ - 有**稳定的 teardown**(清数据、关连接)
102
+ - 失败时有**清晰的错误截图 / 日志**(方便 debug,e2e 失败往往比 unit 难 debug)
103
+
104
+ ---
105
+
106
+ ## 覆盖率目标
107
+
108
+ | 指标 | 底线 | 目标 | 说明 |
109
+ | --- | --- | --- | --- |
110
+ | line coverage | 70% | 80% | 整体;业务核心类 ≥ 90% |
111
+ | branch coverage | 60% | 75% | 更重要;分支没覆盖比行没覆盖更危险 |
112
+ | 核心业务 service | 85% | 95% | 钱 / 券 / 订单 / 库存 等 |
113
+ | controller | 70% | 85% | 主要校验参数和返回 |
114
+ | DAO / Mapper | 30% | 50% | 主要 SQL 正确性,低覆盖容忍(integration 补) |
115
+ | 工具 / helper | 90% | 100% | 纯函数易测 |
116
+ | config / DTO | 忽略 | 忽略 | 无逻辑 |
117
+
118
+ **警告**:追求 100% coverage 会产出"无断言 test"(`@Test public void test() { new Foo().bar(); }`),危害大于收益。目标是**分支充分**,不是行充分。
119
+
120
+ ---
121
+
122
+ ## 什么不值得测
123
+
124
+ | 内容 | 为什么不值得 |
125
+ | --- | --- |
126
+ | Getter / Setter | 没逻辑,测等于没测 |
127
+ | 纯转发(Controller 只调 Service 无参) | integration 覆盖即可 |
128
+ | Spring / ORM 框架本身 | 第三方职责 |
129
+ | 本地日志格式 | 过度约束,日志格式变动常见 |
130
+ | Config loading(读 yaml) | 框架职责 |
131
+ | 显而易见的 null 安全("传 null 不 NPE" 类用例堆砌) | 一两个代表即可 |
132
+ | 每个 exception 类的构造 | 1 条冒烟即可 |
133
+
134
+ **优先级**:先测**业务逻辑 + 边界 + 异常**,再测架构粘合,最后考虑 utility。
135
+
136
+ ---
137
+
138
+ ## 测试的独立性(必须)
139
+
140
+ - **TC-002 必须能在 TC-001 失败时仍然跑通**(不依赖顺序)
141
+ - **每个 case 自清理**(teardown / @AfterEach)
142
+ - **共享数据用 @BeforeAll + immutable fixture**,不要让 case 修改它
143
+ - **避免全局状态**(static 变量 / 线程局部 / 环境变量),非测必要不用
144
+
145
+ ---
146
+
147
+ ## 测试的快速与稳定
148
+
149
+ ### 慢测试的识别与治理
150
+
151
+ - 单元测试 > 500ms 基本都是**写得不对**(有 sleep / 有 real IO)
152
+ - integration 如果单个 > 5s,考虑分拆 + 并行
153
+ - flaky 测试 **必须 quarantine 后立即修**,不能留在主干反复绿红
154
+
155
+ ### 并行化
156
+
157
+ - unit 天然并行:框架自动支持
158
+ - integration 按 test class 并行,注意 DB schema 隔离(每并行组不同 schema)
159
+ - e2e 通常不并行(资源竞争太重)
160
+
161
+ ---
162
+
163
+ ## 回归测试
164
+
165
+ 每次 change 除了本次 new TC,还要**显式列出**受影响的已有 TC(tests.md §7 回归清单):
166
+
167
+ - 改了 `GrantService` 的核心方法 → 列出所有 `GrantServiceTest.*` + `CouponControllerTest.*`
168
+ - 加了索引 → 列出使用旧索引的查询 TC(性能可能变化)
169
+ - 改了 DTO 字段 → 列出所有引用该 DTO 的序列化 TC
170
+
171
+ **关键**:code-review 阶段会扫 §7 是否执行。没跑等于没做。
172
+
173
+ ---
174
+
175
+ ## 性能测试(L3 必有)
176
+
177
+ ### 基线
178
+
179
+ 每个需要 perf TC 的接口都应有一个**基线(baseline)**:
180
+
181
+ - 当前版本的 P50 / P99 / QPS(上线前测过)
182
+ - 新版本测试结果对照基线:**允许 ±5%**,超过要解释
183
+
184
+ ### 场景
185
+
186
+ 至少 3 种:
187
+
188
+ - **典型负载**(日常平均 QPS)
189
+ - **峰值负载**(预计最高 QPS)
190
+ - **稳定性**(峰值 QPS 持续 ≥ 10 分钟 / 1 小时)
191
+
192
+ ### 断言
193
+
194
+ - 吞吐量(QPS)≥ 目标
195
+ - P99 ≤ SLA
196
+ - Error rate < 0.1%
197
+ - 无 Full GC > 200ms(JVM)
198
+ - CPU / memory / DB 连接池无饱和
199
+
200
+ ---
201
+
202
+ ## 框架选型(按语言)
203
+
204
+ | 语言 | unit | integration |
205
+ | --- | --- | --- |
206
+ | Java | JUnit 5 + Mockito + AssertJ | @SpringBootTest + Testcontainers |
207
+ | Go | testing + testify | testify + dockertest / httptest |
208
+ | Python | pytest + pytest-mock | pytest + pytest-docker / testcontainers-python |
209
+ | Node | Jest / Vitest / Mocha | supertest + testcontainers-node |
210
+ | Vue / Frontend | Vitest + @testing-library/vue | Playwright / Cypress(e2e) |
211
+
212
+ 更多语言习语见 `../code-review/references/language-cheatsheets/`。
213
+
214
+ ---
215
+
216
+ ## 本文与 SKILL.md 的关系
217
+
218
+ SKILL.md 只提了金字塔分层和比例。本文给各层测什么 / 不测什么、覆盖率目标、什么不值得测、独立性、快速稳定、回归、性能、框架。test-spec 写 §1 测试策略时应对本文决策。
@@ -0,0 +1,143 @@
1
+ # test-spec / edge-case-to-test
2
+
3
+ 把 `requirement.md §8 边界与异常` 的每一行映射到具体 TC。这是 test-spec 最容易漏的动作。
4
+
5
+ ---
6
+
7
+ ## 映射规则
8
+
9
+ `requirement.md §8` 的每一行 = 至少一个 TC。
10
+
11
+ **映射决策树**:
12
+
13
+ ```
14
+ §8 的一条边界场景
15
+
16
+ Q: 是否可以在 unit 层验证?
17
+ ├─ 是(纯参数 / 内部逻辑) → unit TC
18
+ └─ 否
19
+
20
+ Q: 是否需要真 DB / MQ / HTTP 才能验?
21
+ ├─ 是 → integration TC
22
+ └─ 否(需要跨服务 / UI) → e2e TC
23
+ ```
24
+
25
+ ---
26
+
27
+ ## 边界维度 → TC 骨架的例子库
28
+
29
+ ### 维度 1:空 / 零 / null
30
+
31
+ | §8 场景 | TC 骨架 |
32
+ | --- | --- |
33
+ | 空 userIds → 400 EMPTY_BATCH | TC: unit, preconditions: userIds=[], expected: status=400,code=EMPTY_BATCH |
34
+ | 必填字段 null → 400 | TC: unit, preconditions: {templateId: null}, expected: status=400, code=FIELD_REQUIRED:templateId |
35
+ | 可选字段 null → 200(使用默认) | TC: unit, preconditions: {nickname: null}, expected: status=200,stored 值是默认值 |
36
+
37
+ ### 维度 2:极值
38
+
39
+ | §8 场景 | TC 骨架 |
40
+ | --- | --- |
41
+ | 上限 +1 → 400 | TC: unit, preconditions: 1001 个 userIds, expected: 400 + details.limit/actual |
42
+ | 下限 0 → 400 | 合并到空输入 |
43
+ | 负数 | TC: unit, preconditions: {qty: -1}, expected: 400 FIELD_INVALID |
44
+ | 超大 payload | TC: integration, preconditions: body > 1MB, expected: 413 |
45
+
46
+ ### 维度 3:重复 / 幂等
47
+
48
+ | §8 场景 | TC 骨架 |
49
+ | --- | --- |
50
+ | 同 batchId 重复调 | TC: integration, steps: 1.调一次 2.同 batchId 再调, expected: 两次返回一致,DB 无重复 |
51
+ | batch 内 userId 重复 | TC: unit, preconditions: userIds=[u1,u2,u1], expected: grantedCount=2(去重) |
52
+ | 不同 requestId 但业务重复 | 看业务:是否幂等 → 若是则同上;若否 → 允许产生重复,TC 断言产生 2 条 log |
53
+
54
+ ### 维度 4:并发 / 竞态
55
+
56
+ | §8 场景 | TC 骨架 |
57
+ | --- | --- |
58
+ | 库存扣减并发 | TC: integration, steps: 起 10 个并发线程各减 1, expected: 最终 qty 精确 = 初始 - 10 |
59
+ | 乐观锁冲突 | TC: integration, preconditions: 读取 v=3, steps: 两个 session 同时更新, expected: 一个成功,另一个 409 VERSION_CONFLICT |
60
+ | 分布式锁 | TC: integration, steps: 并发请求同 key, expected: 只一个进入临界区 |
61
+
62
+ ### 维度 5:部分失败
63
+
64
+ | §8 场景 | TC 骨架 |
65
+ | --- | --- |
66
+ | 10/1000 命中风控 | TC: unit, mock RiskService 前 10 人 hit, expected: grantedCount=990, failedUsers.length=10 |
67
+ | 下游 timeout | TC: integration, stub RiskService sleep 5s, expected: 相关用户 reason=TIMEOUT, 整体仍 200 |
68
+ | 事务中途失败 | TC: integration, mock step3 抛异常, expected: step1/2 副作用已回滚 |
69
+
70
+ ### 维度 6:权限 / 越权
71
+
72
+ | §8 场景 | TC 骨架 |
73
+ | --- | --- |
74
+ | 无 token | TC: integration, preconditions: no Authorization header, expected: 401 |
75
+ | token 无此角色 | TC: integration, token 有角色 X 但无 Y, expected: 403 INSUFFICIENT_ROLE |
76
+ | 越权访问 | TC: integration, user A token 访问 user B 资源, expected: 403(不 404,避免泄漏) |
77
+
78
+ ### 维度 7:时区 / 本地化
79
+
80
+ | §8 场景 | TC 骨架 |
81
+ | --- | --- |
82
+ | 过期时间 UTC | TC: unit, set fixed time UTC, expected: 到期判定正确 |
83
+ | emoji 存储 | TC: integration, 传 "👍 中文 en", expected: DB 读回一致 |
84
+ | DST 跨越 | TC: unit, parameterized test on DST 前后的时间段, expected: 时长计算正确 |
85
+
86
+ ### 维度 8:依赖不可用
87
+
88
+ | §8 场景 | TC 骨架 |
89
+ | --- | --- |
90
+ | DB 不可用 | TC: integration, stub DB 抛 connection error, expected: 503 + 指标 db.errors 上报 |
91
+ | 缓存失效 | TC: integration, Redis down, expected: 降级直读 DB(性能指标标记 degraded) |
92
+ | 下游 5xx | TC: integration, stub 返回 500, expected: 本接口 503(不透传) 或 200(降级,具体看设计) |
93
+
94
+ ---
95
+
96
+ ## 映射检查清单(完成后自检)
97
+
98
+ - [ ] §8 的**每一行**是否都找到了对应的 TC?
99
+ - [ ] 对应关系是否**双向可查**?(§8 某行对应 TC-N;TC-N 的 linkedF 里有对应 F-ID 和边界标注)
100
+ - [ ] 每条 TC 的 expected 是否**具体到字段或状态**(不是"应该报错")?
101
+ - [ ] §8 没提到但**想到的边界**,是否反向反馈到 requirement.md §8 补充?
102
+
103
+ ---
104
+
105
+ ## 反向检查:TC 多过 §8?
106
+
107
+ 有时候写 TC 会发现自己在测一个**§8 没列的场景**。这说明:
108
+
109
+ - 要么 requirement 漏写了边界(回退 requirement 补)
110
+ - 要么你在过度测试不重要的东西(删 TC 或标 P2)
111
+
112
+ ---
113
+
114
+ ## AC → TC 的对应(正向路径)
115
+
116
+ 不仅边界,每条 AC 都要有 TC。映射方式:
117
+
118
+ | AC 类型 | TC 数量 |
119
+ | --- | --- |
120
+ | Given-When-Then 单条 AC | 1 个 TC(unit) |
121
+ | AC 含"所有输入"("任何合法 userId") | 1 TC 正向 + 边界各场景的 TC |
122
+ | AC 是性能要求 | 1 个 NFR-PERF-N TC |
123
+ | AC 是可观测性要求 | 嵌入现有 TC 的 expected(断言指标上报) |
124
+
125
+ ---
126
+
127
+ ## F-ID 的 TC 完整度检查
128
+
129
+ 每个 F-ID 扫一遍,对照 `SKILL.md` 的最小映射规则:
130
+
131
+ | Level | F-ID 对应 TC 最少要覆盖 |
132
+ | --- | --- |
133
+ | L1 | 1 正向 |
134
+ | L2 | 1 正向 + 1 边界 + 1 异常 |
135
+ | L3 | 1 正向 + 2 边界 + 1 异常 + 1 NFR |
136
+
137
+ 不达标 → 补 TC 或 F-ID 拆细。
138
+
139
+ ---
140
+
141
+ ## 本文与 SKILL.md 的关系
142
+
143
+ SKILL.md 给了 F-ID → TC 的映射规则表。本文给 `requirement.md §8` 每个边界维度到 TC 骨架的具体映射 + 完整例子库 + 检查清单。test-spec 在写用例前,先按本文把 §8 每一行"翻译"成 TC。