@hupan56/wlkj 3.4.2 → 3.4.3
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.
- package/package.json +1 -1
- package/templates/qoder/commands/wl-code.md +34 -218
- package/templates/qoder/commands/wl-commit.md +46 -43
- package/templates/qoder/commands/wl-prd.md +84 -371
- package/templates/qoder/commands/wl-prd.md.bak +371 -0
- package/templates/qoder/commands/wl-search.md +41 -220
- package/templates/qoder/commands/wl-task.md +622 -619
- package/templates/qoder/commands/wl-test.md +159 -156
|
@@ -1,159 +1,162 @@
|
|
|
1
|
-
---
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
$PY "$R/.qoder/scripts/orchestration/wlkj.py" test
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
JUnit
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
1
|
+
---
|
|
2
|
+
n## 🚨 MCP工具优先,禁跑本地脚本
|
|
3
|
+
所有知识查询走 mcp__qoder-knowledge-graph__ 工具(云平台),绝不跑 wlkj.py kg(本地kg空)。
|
|
4
|
+
|
|
5
|
+
name: wl-test
|
|
6
|
+
description: "测试: quick(意图式用例,默认) / browser(Playwright浏览器) / unit(单元) / coverage(测试覆盖矩阵)。"
|
|
7
|
+
argument-hint: "[quick|browser|unit|coverage] <描述或任务>"
|
|
8
|
+
auto-approve: false
|
|
9
|
+
allowed-tools: [Read, Glob, Grep, Bash, Write, Edit]
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# /wl-test - 测试
|
|
13
|
+
|
|
14
|
+
User input: $ARGUMENTS
|
|
15
|
+
|
|
16
|
+
> ⚠️ DANGEROUS(生成用例 + 可能驱动浏览器)。执行前向用户确认。
|
|
17
|
+
|
|
18
|
+
## 🔧 环境自检(QoderWork 桌面端 vs Qoder IDE/CLI)
|
|
19
|
+
|
|
20
|
+
**先确定仓库根 R**(QoderWork 桌面端工作目录不是仓库根,相对路径会失效):
|
|
21
|
+
```bash
|
|
22
|
+
R=$(python ~/.qoderwork/repo_root.py 2>/dev/null || python3 ~/.qoderwork/repo_root.py 2>/dev/null) || R=.
|
|
23
|
+
PY=$(python --version >/dev/null 2>&1 && echo python || echo python3)
|
|
24
|
+
```
|
|
25
|
+
> 后续脚本统一用 `$PY "$R/.qoder/scripts/orchestration/wlkj.py" <命令>`。
|
|
26
|
+
|
|
27
|
+
## 🚦 第一步:路由(看用户输入,立刻决定走哪条线)
|
|
28
|
+
|
|
29
|
+
**判断 `$ARGUMENTS` 第一个词:**
|
|
30
|
+
- `unit` → 单元测试(读 test-generator skill,跳到本文末尾"unit"段)
|
|
31
|
+
- `browser` 或 含任务名(如 06-14-xxx) → 基于任务的浏览器测试(跳"browser"段)
|
|
32
|
+
- **`coverage` 或 "覆盖""盲区""哪些没测" → 测试覆盖矩阵(跳"coverage"段)**
|
|
33
|
+
- **其他全部 → quick 快速测试**(最常见,如"测一下登录""验下保险页面")
|
|
34
|
+
|
|
35
|
+
用户说"quick 测一下登录" → **quick**。
|
|
36
|
+
用户没说任务名,只是随口"测一下 XX" → **quick**。
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## quick 快速测试(默认 · 零搜索 · 最快)
|
|
41
|
+
|
|
42
|
+
**铁律:quick 模式不搜代码、不读源码、不查 API。** 用户说测什么,AI 直接据常识
|
|
43
|
+
+该页面的通用交互模式生成用例。平台/环境 AI 推断(web 默认、test 默认),
|
|
44
|
+
**只在真不确定平台时才问一句**。不要问地址、不要问登录方式——这些 config/文档里都有。
|
|
45
|
+
|
|
46
|
+
### 🔴 quick 执行铁律(实测踩过的坑,违反 = 测试失败)
|
|
47
|
+
|
|
48
|
+
- **① 用意图式 intent+anchor 格式,禁止旧 action+CSS selector**(如 `input[placeholder*='账号']`)
|
|
49
|
+
- **② 占位符精确用 `{{ask:登录账号}}`/`{{ask:登录密码}}`**(匹配个人文档 key,别写"测试账号")
|
|
50
|
+
- **③ `--cases-file` 传文件,禁止内联 `--cases`**(长 JSON 截断)
|
|
51
|
+
- **④ recall 空时先 navigate+snapshot 拿真实 anchor 再填,禁止预猜 selector**
|
|
52
|
+
- **⑤ URL 写 `{{base_url}}/auth/login`(带斜杠,base_url 已去尾斜杠)**
|
|
53
|
+
- **⑥ recall 的 `--url` 用相对路径 `auth/login`**(前导斜杠会被 Windows Git-bash 转成 `/D:/.../Git/auth/login`)
|
|
54
|
+
- **⑦ Playwright 工具批量加载,snapshot 结果直接读,不写文件再 Read**
|
|
55
|
+
- **⑧ 验证码一气呵成(snapshot→截图→Read→type→点登录→删图),填完立刻提交**
|
|
56
|
+
- **⑨ 用例一次生成全部(正向+异常),别一条一条**
|
|
57
|
+
|
|
58
|
+
### 流程(4 步,不绕弯)
|
|
59
|
+
|
|
60
|
+
**Step 0:recall 查锚点(用相对 URL)。**
|
|
61
|
+
```bash
|
|
62
|
+
$PY "$R/.qoder/scripts/orchestration/wlkj.py" test recall --url auth/login
|
|
63
|
+
```
|
|
64
|
+
- 有锚点 → 直接填进用例 anchor(零 LLM)
|
|
65
|
+
- 无锚点(首次)→ **先 navigate + snapshot 拿真实 a11y 树,从里面提取 anchor**,禁止预猜 selector
|
|
66
|
+
|
|
67
|
+
**Step 1:AI 据用户描述 + 锚点生成用例 JSON。** 不搜代码。常见页面直接写:
|
|
68
|
+
- 登录页:goto `{{base_url}}/auth/login` → 填账号密码 → 点登录 → 断言跳转
|
|
69
|
+
- 列表页:goto 列表 → 断言表格加载 → 翻页/筛选
|
|
70
|
+
- 表单页:goto → 填字段 → 提交 → 断言成功提示
|
|
71
|
+
需要真实数据(账号/密码)用 `{{ask:描述}}` 占位,URL 用 `{{base_url}}/xxx`(**带斜杠**)。
|
|
72
|
+
正向 + 关键异常各一条。**一次生成全部用例。**
|
|
73
|
+
```json
|
|
74
|
+
// ✅ 意图式格式 (anchor 来自 recall 或 snapshot)
|
|
75
|
+
{"intent":"fill","desc":"账号框","value":"{{ask:登录账号}}","anchor":{"role":"textbox","name":"尊敬的管理员"}}
|
|
76
|
+
// ❌ 禁止: 旧 action+CSS selector
|
|
77
|
+
{"action":"fill","target":"input[placeholder*='账号']","value":"{{ask:测试账号}}"}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Step 2:调脚本,注入数据 + 出执行计划:**
|
|
81
|
+
```bash
|
|
82
|
+
# AI 先把用例 JSON 写文件, 再传路径 (--cases-file, 不截断)
|
|
83
|
+
$PY "$R/.qoder/scripts/orchestration/wlkj.py" test quick \
|
|
84
|
+
--cases-file <文件路径> \
|
|
85
|
+
--desc "<用户描述>" --platform <web|app>
|
|
86
|
+
```
|
|
87
|
+
脚本自动:解析 test 环境域名 + 从个人文档注入账号密码 + 出执行计划。
|
|
88
|
+
若提示"需要测试数据" → 逐项问用户,再用 `--data` 传。
|
|
89
|
+
|
|
90
|
+
**Step 3:执行由 Playwright MCP 驱动(真实场景)。**
|
|
91
|
+
脚本只出计划,不自己开浏览器。批量加载 browser_* 工具后按执行计划连发操作。
|
|
92
|
+
跑完回传结果出报告:
|
|
93
|
+
```bash
|
|
94
|
+
$PY "$R/.qoder/scripts/orchestration/wlkj.py" test quick --record '{"Q-1":"pass","Q-2":"fail"}'
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 下一步
|
|
98
|
+
- 用例全过 → `/wl-commit <[#REQ-xxx] message>` 提交回流(双通飞轮:quick 测 → commit 回流 → `/wl-task finish <REQ-ID>` 收尾)
|
|
99
|
+
- 有失败 → 列原因,修复后重跑 quick,再 commit
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## browser 基于任务的浏览器测试(需先有任务)
|
|
104
|
+
|
|
105
|
+
用户明确给了任务名/回归某个任务时走这条。完整流程见 skill。
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
cap.mcp.call("list_tasks", {}) # 确认任务
|
|
109
|
+
$PY "$R/.qoder/scripts/orchestration/wlkj.py" test generate <task> # 生成骨架
|
|
110
|
+
# AI 读任务 PRD「验收标准」补全 steps/expected(真实数据用 {{ask:}})
|
|
111
|
+
$PY "$R/.qoder/scripts/orchestration/wlkj.py" test run <task> # 注入+出执行计划
|
|
112
|
+
$PY "$R/.qoder/scripts/orchestration/wlkj.py" test run <task> --record '{"..":"pass"}' # 回收结果
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## coverage 测试覆盖矩阵(哪些功能有测试 / 哪些是空白)
|
|
118
|
+
|
|
119
|
+
用户说"测试覆盖""哪些没测""回归盲区"时走这条。
|
|
120
|
+
|
|
121
|
+
**调用方式:**
|
|
122
|
+
```
|
|
123
|
+
cap.mcp.call("coverage_matrix", {})
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**FALLBACK: 直接看索引:**
|
|
127
|
+
```bash
|
|
128
|
+
python -c "import json; d=json.load(open('$R/data/index/test-pages.json')); print(json.dumps(d,ensure_ascii=False,indent=2))"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
输出:哪些功能/页面有测试用例(test-pages.json + test-assertions.json),哪些是空白。
|
|
132
|
+
AI 据此建议"优先补 XX 功能的测试"。
|
|
133
|
+
|
|
134
|
+
🎨 **富展示**(覆盖热力图 HTML):`$PY "$R/.qoder/scripts/validation/metrics/present_board.py" coverage --project-id <UUID>`(功能×测试 有/无 热力图,QoderWork 嵌入对话 / CLI 落盘 journal)
|
|
135
|
+
|
|
136
|
+
### 改动驱动的必跑测试(提交前门禁 · S4 覆盖推理)
|
|
137
|
+
|
|
138
|
+
改完代码要确定"必跑哪些测试"时,用覆盖推理四件套(已注册 MCP):
|
|
139
|
+
```python
|
|
140
|
+
cap.mcp.call("impact_coverage", {"entity_ids": ["<改动实体id1>", "<id2>"]}) # 改动集→必跑测试
|
|
141
|
+
cap.mcp.call("find_tests_of", {"entity_id": "<某实体id>"}) # 查某实体的测试
|
|
142
|
+
cap.mcp.call("find_coverage_of", {"req_id": "<REQ-ID>"}) # 查某需求的覆盖
|
|
143
|
+
```
|
|
144
|
+
- `impact_coverage` 拿"这次改动必须跑哪些测试"——提交前用它圈定回归范围,不漏不改崩。
|
|
145
|
+
- 改动实体 id 从 `rag_search`/`search_code` 命中里取。
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## unit 单元测试
|
|
150
|
+
|
|
151
|
+
> **宿主 sub-agent 激活**:QoderWork 支持 sub-agent 时,dispatch 到 **`qoder-test-gen`** agent(`.qoder/agents/qoder-test-gen.toml`)——自动定位实现代码 + 读 Spec → 生成 JUnit(Service 层 Mock 全依赖 Given-When-Then / Controller 层 MockMvc / @DisplayName / AssertJ / Builder 测试数据),输出 `tests/{包路径}/{类名}Test.java`。dispatch prompt 首行传 `Active Code: <实现文件路径>`。不支持则按下文 skill 手动生成。
|
|
152
|
+
|
|
153
|
+
读 `.qoder/skills/test-generator/SKILL.md`:定位实现代码 → 读 spec → 生成
|
|
154
|
+
JUnit 测试(Mock + MockMvc,Given-When-Then)→ 输出 `tests/{package}/{Class}Test.java`。
|
|
155
|
+
(只有这条线才需要 search_index 找代码。)
|
|
156
|
+
|
|
157
|
+
## 报告
|
|
158
|
+
- quick:用例表 + 执行结果(pass/fail),全过建议继续别的,失败列原因
|
|
159
|
+
- browser:同上 + 建议修复重跑或 `/wl-commit`
|
|
157
160
|
|
|
158
161
|
|
|
159
162
|
## 🚨 接地铁律(防幻觉/保真)
|