@wwkit/harness 1.0.28 → 1.0.29

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 (37) hide show
  1. package/bin/index.js +10 -0
  2. package/package.json +3 -2
  3. package/skills/extract/SKILL.md +43 -68
  4. package/skills/extract/references/detail.md +1 -1
  5. package/skills/extract/references/list.md +3 -3
  6. package/skills/extract/references/navi.md +1 -1
  7. package/skills/jstest/SKILL.md +561 -0
  8. package/skills/jstest/references/case-create.md +327 -0
  9. package/skills/jstest/references/case-fix.md +273 -0
  10. package/skills/jstest/references/config.md +148 -0
  11. package/skills/jstest/references/coverage-analyze.md +247 -0
  12. package/skills/jstest/references/env-ensure.md +210 -0
  13. package/skills/jstest/references/execute.md +168 -0
  14. package/skills/jstest/references/sample.md +166 -0
  15. package/skills/jstest/references/scoring-rules.md +75 -0
  16. package/skills/jstest/references/src/jstest-sample/Calculator.js +80 -0
  17. package/skills/jstest/references/src/jstest-sample/ConfigManager.js +72 -0
  18. package/skills/jstest/references/src/jstest-sample/FileProcessor.js +57 -0
  19. package/skills/jstest/references/src/jstest-sample/OrderService.js +98 -0
  20. package/skills/jstest/references/src/jstest-sample/TokenGenerator.js +60 -0
  21. package/skills/jstest/references/src/jstest-sample/UserService.js +56 -0
  22. package/skills/jstest/references/src/jstest-sample/index.js +6 -0
  23. package/skills/jstest/references/suitability-check.md +232 -0
  24. package/skills/jstest/references/test-standards.md +288 -0
  25. package/skills/query/SKILL.md +16 -47
  26. package/skills/revise/SKILL.md +52 -96
  27. package/skills/revise/references/article.md +12 -15
  28. package/skills/revise/references/gallery.md +11 -15
  29. package/skills/revise/references/question.md +11 -15
  30. package/skills/revise/references/status.md +10 -14
  31. package/src/config.js +29 -0
  32. package/src/config.json5 +19 -0
  33. package/skills/extract/references/format-aliases.json5 +0 -22
  34. package/skills/extract/references/input.schema.json5 +0 -23
  35. package/skills/query/references/input.schema.json5 +0 -25
  36. package/skills/revise/references/format-aliases.json5 +0 -22
  37. package/skills/revise/references/input.schema.json5 +0 -28
@@ -0,0 +1,327 @@
1
+ > **原 skill**: `jstest-case-create`(已合并入 jstest)
2
+ > **适用**: 测试代理外层 loop 的用例创建阶段,为未覆盖代码创建测试用例。
3
+ > **不适用**: 修复已有失败用例(使用 jstest-case-fix)、非 jest 框架的用例创建。
4
+
5
+ ---
6
+
7
+ # 测试用例创建
8
+
9
+ ## 工作流模式
10
+
11
+ 本 Skill 采用 **顺序执行** 工作流:
12
+
13
+ 1. **扫描已有测试**:检查目标模块是否已有测试文件,提取已有用例名
14
+ 2. **加载规范**:读取用例创建规范
15
+ 3. **分析源码**:识别未覆盖的函数、分支、异常路径
16
+ 4. **决策 Mock 策略**:按 test_type 选择 Mock 策略
17
+ 5. **创建用例**:增量追加或全新创建
18
+ 6. **语法验证**:验证创建的测试文件语法正确
19
+
20
+ ## 输入
21
+
22
+ | 参数 | 必填 | 类型 | 说明 |
23
+ |------|------|------|------|
24
+ | uncovered_areas | 是 | list/string | 未覆盖区域清单(来自 Step 4(references/coverage-analyze.md),首轮为 "all") |
25
+ | testable_modules | 否 | list | 可测试模块清单(来自 Step 2(references/suitability-check.md),含文件路径+模块名+分类) |
26
+ | target | 是 | string | 被测模块路径 |
27
+ | test_dir | 是 | string | 测试目录路径(由 agent Step 1 统一解析) |
28
+ | test_type | 是 | string | 测试类型:unit 或 integration |
29
+ | config | 是 | object | 来自 Step 3(references/env-ensure.md) 的配置对象 |
30
+
31
+ ## 输出
32
+
33
+ - 新增/追加的测试文件列表(标注是全新创建还是增量追加)
34
+ - 每个文件新增的用例数
35
+ - 跳过的重复用例数
36
+
37
+ ---
38
+
39
+ ## 阶段零:扫描已有测试
40
+
41
+ **操作**:使用 agent 传入的 `test_dir` 直接扫描已有测试,确定工作模式
42
+
43
+ 1. 直接使用传入的 `test_dir` 路径(不再自行推导目录映射)
44
+
45
+ 2. 扫描该目录下是否已有 `*.test.js` 或 `*.test.ts` 文件
46
+
47
+ 3. **无已有文件** → 标记为 `全新模式`,直接进入阶段一
48
+
49
+ 4. **有已有文件** → 标记为 `增量模式`,执行以下操作:
50
+ - 逐个读取已有测试文件
51
+ - 提取已有测试用例名集合(`describe`/`test`/`it` 的完整名称字符串)
52
+ - 提取已有 import 语句和 setup/teardown 定义
53
+ - 记录已有 describe 块名称
54
+
55
+ **决策**:
56
+
57
+ | 模式 | 后续行为 |
58
+ |------|---------|
59
+ | 全新模式 | 创建新文件,从头编写用例 |
60
+ | 增量模式 | 在已有文件中追加 test/it,跳过已存在的用例名 |
61
+
62
+ ---
63
+
64
+ ## 阶段一:加载规范
65
+
66
+ **操作**:读取 `test-standards.md`,加载:
67
+ - 通用规范(AAA、FIRST、命名)
68
+ - JS/jest 特定规范(setup/teardown、mock、test.each)
69
+ - test_type 对应的专属规范
70
+
71
+ ---
72
+
73
+ ## 阶段二:分析源码
74
+
75
+ **输入**:uncovered_areas 清单 + testable_modules 清单(如有)
76
+
77
+ **操作**:
78
+
79
+ 1. 确定待分析源码范围:
80
+ - 如果 `uncovered_areas == "all"`(首轮):扫描 target 目录下所有 .js/.ts 文件
81
+ - 如果 `uncovered_areas` 为列表:仅读取列表中的未覆盖文件
82
+ - 如果提供了 `testable_modules`:仅分析清单中列出的模块,跳过不在清单中的模块
83
+
84
+ 2. 逐个读取待分析的源码文件
85
+
86
+ 3. 分析每个未覆盖函数:
87
+ - 函数签名(参数、返回值、export 方式)
88
+ - 内部分支(if/else/switch)
89
+ - 异常处理(throw/try-catch)
90
+ - 外部依赖(import 的模块、调用的外部方法)
91
+
92
+ 4. 识别需要创建的用例类型:
93
+ - 正向用例(每个公开函数至少 1 个)
94
+ - 边界值用例(有 if/else 分支的函数)
95
+ - 异常路径用例(有 throw/try 的函数)
96
+ - 参数化用例(多输入场景)
97
+
98
+ ---
99
+
100
+ ## 阶段三:决策 Mock 策略
101
+
102
+ **操作**:根据 test_type 从 config 读取 mock_strategy
103
+
104
+ ### unit — mock_strategy=full
105
+
106
+ 按依赖类型选择 Mock 方式:
107
+
108
+ | 依赖类型 | 处理策略 |
109
+ |---------|---------|
110
+ | HTTP 请求 | `jest.mock('axios')` 或 mock fetch,预设 mockResolvedValue |
111
+ | 数据库 | `jest.mock('db-module')` 或 Fake 内存数据库 |
112
+ | 文件系统 | `jest.mock('fs')` 或使用 `os.tmpdir()` |
113
+ | 时间依赖 | `jest.useFakeTimers()` |
114
+ | 随机值 | `jest.spyOn(Math, 'random').mockReturnValue(0.5)` |
115
+ | 外部服务 | `jest.mock('email-module')` 等,验证调用参数 |
116
+ | 环境变量 | `process.env.KEY = 'val'`(直接设置,afterEach 中恢复) |
117
+ | 内部模块 | 优先真实调用,仅 Mock 有副作用的子模块 |
118
+
119
+ ### integration — mock_strategy=minimal
120
+
121
+ | 依赖类型 | 处理策略 |
122
+ |---------|---------|
123
+ | 内部模块 | 真实调用,不 Mock |
124
+ | 数据库 | 真实连接(测试库)或 Fake 内存数据库 |
125
+ | 文件系统 | 真实文件操作(使用 `os.tmpdir()` 清理) |
126
+ | 外部 API | 仅 Mock 不可控的生产 API |
127
+ | 时间/随机 | 可接受真实值,或 `jest.spyOn` 固定 |
128
+
129
+ ---
130
+
131
+ ## 阶段四:创建用例
132
+
133
+ **操作**:
134
+
135
+ ### 全新模式
136
+
137
+ 1. 使用传入的 `test_dir` 确定测试文件路径:
138
+ ```
139
+ test_dir: tests/unit/mypackage/
140
+ 源码文件: src/mypackage/MyService.js
141
+ 测试文件: tests/unit/mypackage/MyService.test.js
142
+ ```
143
+
144
+ 2. 按命名规范创建测试文件:
145
+ - 文件名:`{ModuleName}.test.js`
146
+ - describe 名:`'ModuleName'`
147
+ - test/it 名:`'should {action} {expected}'`
148
+ - 2 空格缩进
149
+ - describe/test/it 结构
150
+
151
+ 3. 按 AAA 模式编写每个用例:
152
+ - Arrange — 准备数据、Mock、setup
153
+ - Act — 调用被测方法
154
+ - Assert — 断言结果
155
+
156
+ ### 增量模式
157
+
158
+ 1. 确定目标测试文件(已存在)
159
+ 2. 读取已有文件内容,保留全部已有代码不动
160
+ 3. 对照阶段零提取的已有用例名集合,跳过已存在的用例
161
+ 4. 在已有 describe 块中追加新 test/it:
162
+ - 用例名:`'should {action} {expected}'`(不与已有用例重名)
163
+ - 仍遵循 AAA 模式
164
+ - 复用已有的 import 和 setup/teardown,仅在需要时追加 import
165
+ 5. 如果已有文件中没有对应的 describe 块(源码新增了模块),则在该文件中新增 describe 块
166
+
167
+ **通用规则**(两种模式共用):
168
+
169
+ 1. 按用例类型创建:
170
+ - 正向用例:正常输入 → 预期输出
171
+ - 边界用例:边界值 → 预期行为
172
+ - 异常用例:非法输入 → `expect(() => fn()).toThrow(Error)` 或 `expect(fn()).toThrow('message')`
173
+ - 参数化用例:`test.each([[1, true], [2, false]])('should validate %i', (input, expected) => { ... })`
174
+
175
+ 2. 检查 jest 配置(setupFiles / jest.setup.js):
176
+ - 检查 test_dir 下是否有 jest.setup.js 或 package.json 中有 setupFiles 配置 → 有则不修改
177
+ - 检查 test_dir 的父目录是否有 jest 配置 → 有则不创建,提示"父目录已有 jest 配置"
178
+ - 均无 jest 配置 → 不创建 setupFiles(除非 test_dir 下完全没有任何 jest 配置,此时仅在 package.json 的 jest 字段中添加最小 setupFiles)
179
+ - 不导入任何项目特定的三方库到 setupFiles
180
+
181
+ **创建示例**:
182
+
183
+ ```javascript
184
+ import { MyService } from '../../../src/mypackage/MyService.js';
185
+
186
+ jest.mock('../../../src/mypackage/MyService.js');
187
+
188
+ describe('MyService', () => {
189
+ test('should create with valid data', () => {
190
+ // Arrange
191
+ const service = new MyService();
192
+ const data = { name: 'test', age: 18 };
193
+ // Act
194
+ const result = service.create(data);
195
+ // Assert
196
+ expect(result.id).toBeDefined();
197
+ expect(result.name).toBe('test');
198
+ });
199
+
200
+ test('should throw on empty name', () => {
201
+ // Arrange
202
+ const service = new MyService();
203
+ // Act & Assert
204
+ expect(() => service.create({ name: '' })).toThrow('name不能为空');
205
+ });
206
+
207
+ test.each([
208
+ [18, true],
209
+ [30, true],
210
+ [17, false],
211
+ [61, false],
212
+ ])('should validate age %i → %s', (age, expected) => {
213
+ const service = new MyService();
214
+ const result = service.validateAge(age);
215
+ expect(result).toBe(expected);
216
+ });
217
+ });
218
+ ```
219
+
220
+ ---
221
+
222
+ ## 阶段五:语法验证
223
+
224
+ **操作**:
225
+
226
+ 1. 对每个新创建的测试文件运行语法检查:
227
+ ```
228
+ node --check "<test_file>"
229
+ ```
230
+
231
+ 2. 语法错误 → 修复后重新验证
232
+
233
+ **决策**:
234
+
235
+ | 条件 | 动作 |
236
+ |------|------|
237
+ | 全部语法正确 | 输出创建结果 |
238
+ | 有语法错误 | 修复后重新验证,最多 3 次 |
239
+ | 修复 3 次仍失败 | 记录错误,跳过该文件 |
240
+
241
+ ---
242
+
243
+ ## 输出格式
244
+
245
+ ```
246
+ ## 用例创建报告
247
+
248
+ ### 工作模式
249
+ - 模式: [全新模式 / 增量模式]
250
+ - 已有测试文件: X 个(增量模式时显示)
251
+
252
+ ### 新增/追加测试文件
253
+ | 文件路径 | 模式 | 新增用例数 | 跳过重复 | 覆盖函数 |
254
+ |---------|------|-----------|---------|---------|
255
+ | tests/unit/mypackage/MyService.test.js | 全新创建 | 8 | 0 | create, validate, parse |
256
+ | tests/unit/mypackage/OtherService.test.js | 增量追加 | 3 | 2 | update, delete |
257
+
258
+ ### 用例明细
259
+ | 用例名 | 类型 | 被测函数 |
260
+ |--------|------|---------|
261
+ | should create with valid data | 正向 | create |
262
+ | should throw on empty name | 异常 | create |
263
+ | should validate age boundary | 边界 | validate |
264
+
265
+ ### Mock 使用
266
+ | 依赖类型 | Mock 方式 |
267
+ |---------|---------|
268
+ | HTTP | jest.mock('axios') |
269
+ | 文件 | jest.mock('fs') |
270
+ ```
271
+
272
+ ### 0 新用例检测
273
+
274
+ 阶段四完成后,统计新增用例总数。如果为 0(所有方法均已存在),输出特殊标记:
275
+
276
+ ```
277
+ ## 用例创建报告
278
+
279
+ ### 工作模式
280
+ - 模式: 增量模式
281
+ - 新增用例数: 0
282
+
283
+ ### 结论
284
+ - [0 新用例] 所有未覆盖区域已有对应测试,无法通过新增用例提升覆盖率
285
+ - 建议: 检查已有用例质量(断言完整性、边界值覆盖),或确认覆盖率瓶颈原因
286
+ ```
287
+
288
+ agent 收到此标记后,应跳过 execute + fix,直接回到 coverage-analyze 重新评分或判定"无改进"退出。
289
+
290
+ ## 失败处理
291
+
292
+ | 场景 | 处理方式 |
293
+ |------|---------|
294
+ | 源码文件不存在 | 跳过,记录警告 |
295
+ | 源码无法分析(语法错误) | 跳过,记录错误 |
296
+ | 测试目录不存在 | 自动创建 |
297
+ | 语法验证失败 | 修复重试,最多 3 次 |
298
+ | jest.setup.js 已存在 | 不修改 |
299
+ | 已有测试文件语法错误 | 跳过该文件的追加,记录警告 |
300
+ | uncovered_areas 为空列表 | 输出"无需新建用例,建议改进已有用例质量",返回给 agent |
301
+ | 新增用例数为 0(全部重复) | 输出"0 新用例"标记,agent 应跳过 execute+fix |
302
+
303
+ ## 一定要做
304
+
305
+ 1. 必须先扫描已有测试文件,确定工作模式(全新/增量)
306
+ 2. 增量模式下必须保留已有代码不动,只追加新 test/it
307
+ 3. 必须根据 test_type 选择对应的 Mock 策略
308
+ 4. 如果提供了 testable_modules,必须仅对清单中的模块创建测试,跳过不在清单中的模块
309
+ 5. 如果 uncovered_areas 为 "all"(首轮),必须扫描全部源码文件
310
+ 6. 必须遵循命名规范({ModuleName}.test.js 文件名、describe('ModuleName')、test('should ...'))
311
+ 7. 必须遵循 AAA 模式
312
+ 8. 必须为每个未覆盖函数创建至少 1 个正向用例
313
+ 9. 有分支的函数必须创建边界值用例
314
+ 10. 有异常处理的函数必须创建异常路径用例
315
+ 11. 创建后必须验证语法正确
316
+ 12. 遵循 AGENTS.md:2 空格缩进、describe/test/it 结构
317
+
318
+ ## 一定不要做
319
+
320
+ 1. 不要修改源码文件
321
+ 2. 不要覆盖已有测试文件中的已有用例
322
+ 3. 不要创建与现有测试重复的用例(用例名相同的跳过)
323
+ 4. 不要在单元测试中使用真实网络/文件/时间调用
324
+ 5. 不要修改已存在的 jest.setup.js 或 setupFiles 配置
325
+ 6. 不要导入项目特定的三方库到 setupFiles
326
+ 7. 不要跳过语法验证
327
+ 8. 不要使用 class 风格(统一用 describe/test/it 函数式)
@@ -0,0 +1,273 @@
1
+ > **原 skill**: `jstest-case-fix`(已合并入 jstest)
2
+ > **适用**: 测试代理内层 loop 的修复阶段,修复 jstest-execute 报告的失败用例。
3
+ > **不适用**: 创建新用例(使用 jstest-case-create)、覆盖率分析(使用 jstest-coverage-analyze)。
4
+
5
+ ---
6
+
7
+ # 用例修复
8
+
9
+ ## 工作流模式
10
+
11
+ 本 Skill 采用 **顺序执行** 工作流:
12
+
13
+ 1. **分类失败**:按错误类型对失败用例分类
14
+ 2. **分析原因**:逐个分析失败根因
15
+ 3. **执行修复**:按分类进行修复
16
+ 4. **语法验证**:验证修复后的文件语法正确
17
+ 5. **输出记录**:修复记录 + 人工处理项 + 源码 Bug 清单(写入 `{report_dir}/bug_list.md`)
18
+
19
+ ## 输入
20
+
21
+ | 参数 | 必填 | 类型 | 说明 |
22
+ |------|------|------|------|
23
+ | failed_tests | 是 | list | 失败用例清单(来自 Step 6(references/execute.md)) |
24
+ | test_dir | 是 | string | 测试目录路径(由 agent Step 1 统一解析) |
25
+ | report_dir | 是 | string | 报告输出目录(由 agent Step 1 统一解析) |
26
+ | test_type | 是 | string | 测试类型:unit 或 integration |
27
+ | config | 是 | object | 来自 jstest-env-ensure 的配置对象 |
28
+
29
+ ## 输出
30
+
31
+ - 修复记录列表
32
+ - 人工处理项列表
33
+ - 源码 Bug 清单(已修复 + 需人工处理)
34
+ - 是否有修改的结论(有修改 → 回到 execute;无修改 → 内层 loop 退出)
35
+ - 将源码 Bug 清单写入 `{report_dir}/bug_list.md`
36
+
37
+ ---
38
+
39
+ ## 阶段一:分类失败
40
+
41
+ **操作**:按错误类型对失败用例分类
42
+
43
+ | 分类 | 错误类型 | 说明 |
44
+ |------|---------|------|
45
+ | 断言失败 | AssertionError | 测试逻辑有误或源码有 bug |
46
+ | Mock 配置错误 | TypeError, ReferenceError | jest.mock 路径不对或 Mock 对象属性缺失 |
47
+ | 导入错误 | Cannot find module, SyntaxError | 依赖缺失,环境问题 |
48
+ | 超时 | Exceeded timeout | 可能有真实网络调用未被 Mock |
49
+ | 其他 | 其他异常 | 未知错误 |
50
+
51
+ ---
52
+
53
+ ## 阶段二:分析原因
54
+
55
+ ### 断言失败(AssertionError)
56
+
57
+ 逐个分析:
58
+
59
+ 1. 读取测试用例代码
60
+ 2. 读取被测源码
61
+ 3. 判断失败原因:
62
+ - **测试逻辑有误**:断言条件写错 → 修复测试
63
+ - **Mock 返回值不对**:mockResolvedValue/mockReturnValue 数据与预期不符 → 修复 Mock 返回值
64
+ - **源码逻辑有 bug**:测试暴露了真实缺陷 → 修复源码
65
+
66
+ ### Mock 配置错误(TypeError, ReferenceError)
67
+
68
+ 1. 检查 `jest.mock()` 路径是否正确
69
+ 2. 检查 Mock 对象是否配置了所需的属性/方法
70
+ 3. 检查 `mockReturnValue` / `mockResolvedValue` / `mockImplementation` 是否设置
71
+
72
+ ### 导入错误(Cannot find module, SyntaxError)
73
+
74
+ 1. 检查是否缺少依赖包
75
+ 2. 检查 ESM/CJS 模块系统是否匹配
76
+ 3. 标记为 **人工处理**,不在 fix 轮次中解决
77
+
78
+ ### 超时(Exceeded timeout)
79
+
80
+ 1. 检查是否有真实网络调用未被 Mock
81
+ 2. 修复为 Mock 调用(unit 类型)
82
+ 3. 集成测试的超时可能是环境问题 → 标记人工处理
83
+
84
+ ### 其他
85
+
86
+ 1. 记录详细错误信息
87
+ 2. 标记为 **人工处理**
88
+
89
+ ---
90
+
91
+ ## 阶段三:执行修复
92
+
93
+ ### 修复测试用例
94
+
95
+ | 场景 | 修复操作 |
96
+ |------|---------|
97
+ | 断言条件写错 | 修正 expect 表达式 |
98
+ | Mock 返回值不对 | 修改 mockReturnValue/mockResolvedValue 为正确值 |
99
+ | jest.mock 路径不对 | 修正 jest.mock 路径为正确的模块路径 |
100
+ | Mock 属性缺失 | 添加 mockImplementation 或配置 Mock 对象属性 |
101
+ | Stub 数据格式不对 | 修正 Stub 数据结构 |
102
+ | 测试数据有误 | 修正测试输入数据 |
103
+
104
+ ### 修复源码
105
+
106
+ | 场景 | 修复操作 |
107
+ |------|---------|
108
+ | 函数返回值有误 | 修正返回逻辑 |
109
+ | 异常处理不完整 | 补充 try-catch 分支 |
110
+ | 边界条件处理错误 | 修正条件判断 |
111
+ | 类型转换错误 | 修正类型处理 |
112
+
113
+ ### 修复原则
114
+
115
+ 1. **只修复失败相关的代码**,不改动其他部分
116
+ 2. **修复测试优先于修复源码**(先确认测试正确,再修源码)
117
+ 3. **一次只修一个失败**,避免引入新问题
118
+ 4. **不修改 jest 配置文件或 setupFiles**(除非失败直接由配置导致)
119
+ 5. **修改源码前必须保存原始内容**(读取并记录文件原始内容,用于回滚)
120
+
121
+ ---
122
+
123
+ ## 阶段四:语法验证与快速测试
124
+
125
+ **操作**:
126
+
127
+ ### 4.1 语法检查
128
+
129
+ 对每个修复的文件运行语法检查:
130
+
131
+ ```
132
+ node --check "<file>"
133
+ ```
134
+
135
+ ### 4.2 源码修复的快速测试
136
+
137
+ 如果修复了**源码文件**(非测试文件),额外运行对应测试文件的快速验证:
138
+
139
+ ```
140
+ node --experimental-vm-modules node_modules/jest/bin/jest.js --no-cache --verbose --testTimeout=60000 "<对应测试文件>"
141
+ ```
142
+
143
+ **目的**:`node --check` 只检查语法,无法发现运行时错误(类型错误、属性不存在等)。快速测试确保源码修复不引入新问题。
144
+
145
+ ### 4.3 回滚机制
146
+
147
+ - 阶段三修复前已保存原始内容
148
+ - 语法检查失败或快速测试引入新错误 → 用原始内容覆盖文件,回滚修改
149
+ - 回滚后标记为人工处理
150
+
151
+ **决策**:
152
+
153
+ | 条件 | 动作 |
154
+ |------|------|
155
+ | 语法正确 + 快速测试通过(或无源码修复) | 进入阶段五 |
156
+ | 语法错误 | 用原始内容回滚,标记为人工处理 |
157
+ | 快速测试引入新错误 | 用原始内容回滚,标记为人工处理 |
158
+ | 快速测试超时 | 回滚源码修改,标记为人工处理 |
159
+
160
+ ---
161
+
162
+ ## 阶段五:输出记录
163
+
164
+ **操作**:
165
+
166
+ 1. 在 chat 中输出修复报告
167
+ 2. 将源码 Bug 清单写入 `{report_dir}/bug_list.md`
168
+
169
+ ### 修复报告(chat 输出)
170
+
171
+ ```
172
+ ## 用例修复报告
173
+
174
+ ### 修复记录
175
+ | # | 文件 | 用例名 | 失败类型 | 修复类型 | 修复内容 |
176
+ |---|------|--------|---------|---------|---------|
177
+ | 1 | MyService.test.js | should create with valid data | 断言失败 | 修复测试 | 修正 expect 条件 |
178
+ | 2 | MyService.js | - | 断言失败 | 修复源码 | 修正返回值逻辑 |
179
+ | 3 | MyService.test.js | should parse on empty input | Mock错误 | 修复测试 | 修正 jest.mock 路径 |
180
+
181
+ ### 人工处理项
182
+ | # | 文件 | 用例名 | 失败类型 | 原因 |
183
+ |---|------|--------|---------|------|
184
+ | 4 | MyService.test.js | should import module | 导入错误 | Cannot find module 'xxx' |
185
+
186
+ ### 结论
187
+ - 修复 X 项,人工处理 Y 项
188
+ - [有修改] → 建议重新执行测试
189
+ - [无修改] → 无法自动修复,建议人工介入
190
+ ```
191
+
192
+ ### 源码 Bug 清单(写入 {report_dir}/bug_list.md)
193
+
194
+ 仅记录修复类型为"修复源码"的条目,以及源码层面无法自动修复需人工处理的条目。
195
+
196
+ ```markdown
197
+ # 源码 Bug 清单
198
+
199
+ > 生成时间: {YYYY-MM-DD HH:MM:SS}
200
+ > 测试类型: {test_type}
201
+ > 测试目录: {test_dir}
202
+
203
+ ## 已自动修复
204
+
205
+ | # | 源码文件 | 方法 | Bug 描述 | 修复内容 | 触发用例 |
206
+ |---|---------|------|---------|---------|---------|
207
+ | 1 | MyService.js | create | 返回值逻辑错误 | 修正返回值 | should create with valid data |
208
+ | 2 | Calculator.js | clamp | min/max 返回值互换 | 修正分支逻辑 | should clamp boundary |
209
+
210
+ ## 需人工处理
211
+
212
+ | # | 源码文件 | 方法 | Bug 描述 | 原因 | 触发用例 |
213
+ |---|---------|------|---------|------|---------|
214
+ | 3 | OrderService.js | createOrder | 类型校验缺失 | 需业务确认预期行为 | should create order with invalid user id |
215
+ | 4 | ConfigManager.js | getBool | truthy 逻辑反转 | 修复后语法错误已回滚,需人工分析 | should get bool unknown value |
216
+ ```
217
+
218
+ **源码 Bug 判定规则**:
219
+
220
+ | 条件 | 归类 |
221
+ |------|------|
222
+ | 阶段二判定为"源码逻辑有 bug"且阶段三成功修复 | 已自动修复 |
223
+ | 阶段二判定为"源码逻辑有 bug"但修复后语法验证失败已回滚 | 需人工处理 |
224
+ | 阶段二判定为"源码逻辑有 bug"但无法确定修复方案 | 需人工处理 |
225
+
226
+ **文件写入规则**:
227
+ - 路径:`{report_dir}/bug_list.md`
228
+ - 目录不存在时自动创建
229
+ - 每次内层 loop 执行时覆盖写入(保留最新状态)
230
+ - 无源码 Bug 时仍写入文件,内容为"本次测试未发现源码 Bug"
231
+
232
+ ---
233
+
234
+ ## 决策
235
+
236
+ | 条件 | 动作 |
237
+ |------|------|
238
+ | 有修复(修复数 > 0) | 输出修复记录,回到 Step 6(按 references/execute.md 执行) 重新执行 |
239
+ | 无修复(全部标记人工处理) | 输出人工处理项,内层 loop 提前退出 |
240
+
241
+ ## 失败处理
242
+
243
+ | 场景 | 处理方式 |
244
+ |------|---------|
245
+ | 修复后语法错误 | 回滚该文件修改,标记人工处理 |
246
+ | 无法确定失败原因 | 记录详情,标记人工处理 |
247
+ | 源码修复引入新问题 | 回滚源码修改,标记人工处理 |
248
+
249
+ ## 一定要做
250
+
251
+ 1. 必须按错误类型分类处理
252
+ 2. 修复测试优先于修复源码
253
+ 3. 一次只修一个失败
254
+ 4. 修改源码前必须保存原始内容(用于回滚)
255
+ 5. 修复后必须验证语法
256
+ 6. 源码修复后必须运行对应测试的快速验证(防止引入新问题)
257
+ 7. 语法错误或快速测试失败必须回滚(用原始内容覆盖)
258
+ 8. 无法修复的必须标记为人工处理
259
+ 9. 必须输出是否有修改的结论
260
+ 10. 修复源码的条目必须记录到源码 Bug 清单
261
+ 11. 源码 Bug 清单必须写入 `{report_dir}/bug_list.md`
262
+ 12. 无源码 Bug 时仍写入 bug_list.md,内容为"本次测试未发现源码 Bug"
263
+
264
+ ## 一定不要做
265
+
266
+ 1. 不要修改与失败无关的代码
267
+ 2. 不要修改 jest 配置文件或 setupFiles(除非直接导致失败)
268
+ 3. 不要在一次修复中改动多个文件(逐个修复)
269
+ 4. 不要跳过语法验证
270
+ 5. 不要跳过源码修复后的快速测试
271
+ 6. 不要忽略语法验证或快速测试失败(必须回滚)
272
+ 7. 不要尝试修复导入错误(标记人工处理)
273
+ 8. 不要在未保存原始内容的情况下修改源码(无法回滚)