csspilot 0.7.1 → 0.7.2

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.
@@ -2,10 +2,13 @@
2
2
  # `npx csspilot init` 会把整个 skills/testpilot/ 安装到业务项目 .agents/skills/testpilot/
3
3
  id: testpilot
4
4
  name: TestPilot
5
- version: 0.6.0
5
+ version: 0.7.0
6
6
 
7
7
  description: >
8
8
  AI Native cross-platform testing skill.
9
+ Miniapp deep-testing actions: mockWxApi / callWxApi / trigger / callMethod /
10
+ setData / dataPath-assert / count-assert / attribute-assert / longpress /
11
+ touch / scroll / swipeTo / slideTo / moveTo.
9
12
 
10
13
  capabilities:
11
14
  - test-requirements-review
@@ -1,47 +1,47 @@
1
- # Case 设计规范
2
-
3
- ## Case 属于业务项目
4
-
5
- - Case 只存在于业务项目的 `tests/e2e/cases/`,永远不要写进 TestPilot 仓库的 `packages/`。
6
- - 一个 Case 描述一条完整的业务流程(如:创建订单、提交退款),不是单个页面操作。
7
- - `id` 使用 kebab-case,与文件名一致:`order-create.yaml` → `id: order-create`。
8
-
9
- ## Case 与数据行
10
-
11
- - 默认一条独立业务流程一个 Case。
12
- - 多个测试点的步骤模板完全相同、差异仅为输入数据和可判定预期时,允许合并为一个 data-driven Case。
13
- - 每个 dataset 行必须有稳定唯一的 rowId,并仍保持“一个可判定规则/数据点”粒度。
14
- - 不同页面路径、不同角色权限流程、不同清理策略或不同断言结构不得为了减少 Case 数量而强行合并。
15
- - 报告按 `caseId#rowId` 标识执行结果;统计时每个数据行算一次执行。
16
-
17
- ## AI 不能凭空生成测试
18
-
19
- 正确路径:
20
-
21
- ```text
22
- 用户需求 → 代码 / 页面 / 配置 → Evidence → 测试步骤 → Case
23
- ```
24
-
25
- 禁止路径:
26
-
27
- ```text
28
- 用户需求 → AI 猜 → Case
29
- ```
30
-
31
- 看到"测试登录"就直接写 `locator: { text: 登录 }` 是错误的。
32
- 必须先阅读项目真实页面/代码,确认元素存在、文案准确,再生成步骤。
33
-
34
- ## 业务数据
35
-
36
- - 不要把业务账号、密码硬编码进 Case。
37
- - 测试参数统一放业务项目 `tests/e2e/data/` 的 YAML/JSON 文件,Case 通过 `${fixture.*}` / `${dataset.*}` 引用。
38
- - `requires` 只声明当前 Case 有证据支持的静态依赖。AI 必须从 PRD/Spec、代码、配置、已有 Case 或 QA 用例识别,不得因为业务名称自动发明账号、优惠券、PPM 等字段。
39
- - `.env` 提供当前环境的实际值;只有 `testpilot.yaml variables` 白名单映射的值可通过 `${variable.*}` 暴露给 Case。
40
- - 缺失依赖会使该数据行 `skipped(dependency-not-ready)`,这只表示静态值未就绪,不保证远端业务对象有效。
41
- - setup/teardown 优先使用 API 造数和清理;teardown 必须可重复执行。
42
-
43
- ## charter:* 视角标签
44
-
45
- - `charter:` 前缀为评审视角保留标签(命名固定,勿作他用):`charter:persona` / `charter:edge-input` / `charter:numbers-copy` / `charter:state-recovery` / `charter:error-path`。
46
- - 由需求评审的视角覆盖表驱动写入(见 `workflows/create-case.md`);视角在需求内不适用时不打对应 tag。
47
- - 按视角抽查覆盖:`npx csspilot list --tag charter:error-path`。
1
+ # Case 设计规范
2
+
3
+ ## Case 属于业务项目
4
+
5
+ - Case 只存在于业务项目的 `tests/e2e/cases/`,永远不要写进 TestPilot 仓库的 `packages/`。
6
+ - 一个 Case 描述一条完整的业务流程(如:创建订单、提交退款),不是单个页面操作。
7
+ - `id` 使用 kebab-case,与文件名一致:`order-create.yaml` → `id: order-create`。
8
+
9
+ ## Case 与数据行
10
+
11
+ - 默认一条独立业务流程一个 Case。
12
+ - 多个测试点的步骤模板完全相同、差异仅为输入数据和可判定预期时,允许合并为一个 data-driven Case。
13
+ - 每个 dataset 行必须有稳定唯一的 rowId,并仍保持“一个可判定规则/数据点”粒度。
14
+ - 不同页面路径、不同角色权限流程、不同清理策略或不同断言结构不得为了减少 Case 数量而强行合并。
15
+ - 报告按 `caseId#rowId` 标识执行结果;统计时每个数据行算一次执行。
16
+
17
+ ## AI 不能凭空生成测试
18
+
19
+ 正确路径:
20
+
21
+ ```text
22
+ 用户需求 → 代码 / 页面 / 配置 → Evidence → 测试步骤 → Case
23
+ ```
24
+
25
+ 禁止路径:
26
+
27
+ ```text
28
+ 用户需求 → AI 猜 → Case
29
+ ```
30
+
31
+ 看到"测试登录"就直接写 `locator: { text: 登录 }` 是错误的。
32
+ 必须先阅读项目真实页面/代码,确认元素存在、文案准确,再生成步骤。
33
+
34
+ ## 业务数据
35
+
36
+ - 不要把业务账号、密码硬编码进 Case。
37
+ - 测试参数统一放业务项目 `tests/e2e/data/` 的 YAML/JSON 文件,Case 通过 `${fixture.*}` / `${dataset.*}` 引用。
38
+ - `requires` 只声明当前 Case 有证据支持的静态依赖。AI 必须从 PRD/Spec、代码、配置、已有 Case 或 QA 用例识别,不得因为业务名称自动发明账号、优惠券、PPM 等字段。
39
+ - `.env.testing` 提供当前环境的实际值(只放测试变量,不读前端项目自身的 `.env`);只有 `testpilot.yaml variables` 白名单映射的值可通过 `${variable.*}` 暴露给 Case。
40
+ - 缺失依赖会使该数据行 `skipped(dependency-not-ready)`,这只表示静态值未就绪,不保证远端业务对象有效。
41
+ - setup/teardown 优先使用 API 造数和清理;teardown 必须可重复执行。
42
+
43
+ ## charter:* 视角标签
44
+
45
+ - `charter:` 前缀为评审视角保留标签(命名固定,勿作他用):`charter:persona` / `charter:edge-input` / `charter:numbers-copy` / `charter:state-recovery` / `charter:error-path`。
46
+ - 由需求评审的视角覆盖表驱动写入(见 `workflows/create-case.md`);视角在需求内不适用时不打对应 tag。
47
+ - 按视角抽查覆盖:`npx csspilot list --tag charter:error-path`。
@@ -1,6 +1,6 @@
1
1
  # DSL 规范
2
2
 
3
- Case 是 YAML 文件,V0.1 顶层结构:
3
+ Case 是 YAML 文件,顶层结构:
4
4
 
5
5
  ```yaml
6
6
  id: order-create # kebab-case,与文件名一致
@@ -31,20 +31,127 @@ teardown: # 可选:setup 开始后始终执行
31
31
  method: DELETE
32
32
  ```
33
33
 
34
- ## V0.1 稳定 Action
34
+ ## Action 总表
35
+
36
+ ### 通用与 UI 基础
35
37
 
36
38
  | action | 用途 | 支持端 | 关键字段 |
37
39
  | --- | --- | --- | --- |
38
- | `launch` | 启动应用(miniapp) | miniapp | — |
39
- | `navigate` | 打开页面(web) | web, miniapp | `url` |
40
+ | `launch` | 启动应用 | web, miniapp | — |
41
+ | `navigate` | 打开页面(miniapp 为小程序路由 reLaunch) | web, miniapp | `url` |
40
42
  | `click` | 点击 | web, miniapp | `locator` |
43
+ | `longpress` | 长按(小程序原生;web 以按住 ~600ms 近似) | web, miniapp | `locator` |
41
44
  | `input` | 输入 | web, miniapp | `locator`, `value` |
42
- | `select` | 选择 | web | `locator`, `value` |
43
- | `wait` | 等待 | web, miniapp | 条件(以 @testpilot/dsl schema 为准) |
44
- | `assert` | 断言 | web, miniapp, api | `locator`+`expected`(UI)/`expected`(api 响应体包含) |
45
- | `extract` | 提取内容为变量 | web, miniapp, api | `locator`+变量名(UI)/`value`(JSON path)+变量名(api) |
45
+ | `select` | 下拉选择(小程序 picker 暂不支持) | web | `locator`, `value` |
46
+ | `wait` | 等待元素出现或等待毫秒 | web, miniapp | `locator` 或 `timeout` |
46
47
  | `screenshot` | 截图取证 | web, miniapp | — |
47
- | `request` | HTTP 请求 | api | `url`, `method`, `headers`, `body`, `expected`(状态码) |
48
+
49
+ ### 断言与提取
50
+
51
+ | action | 用途 | 支持端 | 关键字段 |
52
+ | --- | --- | --- | --- |
53
+ | `assert` | 断言,见下方四种模式 | web, miniapp, api | 见下 |
54
+ | `extract` | 提取内容为变量(UI 元素文本 / api JSON path) | web, miniapp, api | `locator` 或 `value`(api),`variable` |
55
+
56
+ `assert` 的四种模式(互斥,一套步骤只能选一种):
57
+
58
+ ```yaml
59
+ # 1) 文本断言(缺省):元素文本包含 expected
60
+ - target: miniapp
61
+ action: assert
62
+ locator: { css: ".order-id" }
63
+ expected: "${orderId}"
64
+
65
+ # 2) 页面 data 断言(dataPath,仅 miniapp):页面 data 路径的值包含 expected
66
+ - target: miniapp
67
+ action: assert
68
+ dataPath: status
69
+ expected: expired
70
+
71
+ # 3) 属性断言(attribute web/miniapp;property 仅 miniapp):String(值) 与 expected 全等
72
+ - target: miniapp
73
+ action: assert
74
+ locator: { css: ".submit-btn" }
75
+ attribute: disabled # 或 property: status(自定义组件实例属性)
76
+ expected: "true" # 属性不存在时实际值为 <absent>
77
+
78
+ # 4) 数量断言(count):匹配元素的精确数量,0 即"元素不存在";不需要 expected
79
+ - target: miniapp
80
+ action: assert
81
+ locator: { css: ".cart-item" }
82
+ count: 3
83
+ ```
84
+
85
+ ### 网络断言与 API 端
86
+
87
+ | action | 用途 | 支持端 | 关键字段 |
88
+ | --- | --- | --- | --- |
89
+ | `request` | HTTP 请求(可断言状态码) | api | `url`, `method`, `headers`, `body`, `expected`(状态码) |
90
+
91
+ `expectRequests` 可附在 web/miniapp 的 `navigate`、`click`、`input`、`select` 上做请求次数精确断言(只观察不拦截),见下文。
92
+
93
+ ### 小程序深度测试(仅 miniapp)
94
+
95
+ | action | 用途 | 关键字段 |
96
+ | --- | --- | --- |
97
+ | `callMethod` | 调用 Page 方法(locator 缺省)或组件实例方法(提供 locator) | `methodName`, `args`, `locator`(可选) |
98
+ | `setData` | 写入页面 data(locator 缺省)或组件 data(提供 locator)补丁,驱动 onShow/onPullDownRefresh 等真实链路 | `patch`, `locator`(可选) |
99
+ | `trigger` | 对组件注入事件(如 `getphonenumber` + 空 detail = 用户拒绝授权分支) | `locator`, `eventType`, `detail` |
100
+ | `mockWxApi` | 拦截 wx.* API 返回 mock 值;`capture` 记录真实调用参数到变量(`${<capture>.options}` / 列表),step 结束自动恢复 | `wxApi`, `result`, `capture` |
101
+ | `callWxApi` | 主动调用 wx.* API 造前置状态(如 `setStorageSync` 写登录态、`clearStorageSync` 制造未授权设备);返回值可用 `variable` 捕获 | `wxApi`, `args`, `variable` |
102
+ | `touch` | 派发触摸事件(自定义手势组件) | `locator`, `phase`(touchstart/touchmove/touchend), `touches` |
103
+ | `scroll` | 滚动 scroll-view 元素(提供 locator)或页面(缺省) | `scrollTop`, `locator`(可选) |
104
+ | `swipeTo` | swiper 切到指定页 | `locator`, `index` |
105
+ | `slideTo` | slider 滑到指定值 | `locator`, `value`(数字) |
106
+ | `moveTo` | movable-view 移动到坐标 | `locator`, `x`, `y` |
107
+
108
+ 示例:mock 后端响应驱动分支 + 断言页面状态机(不需要后端造数):
109
+
110
+ ```yaml
111
+ steps:
112
+ - target: miniapp
113
+ action: launch
114
+ # mock wx.request 使登录接口返回 needPhoneAuth,直接进入待授权分支
115
+ - target: miniapp
116
+ action: mockWxApi
117
+ wxApi: request
118
+ result: { needPhoneAuth: true }
119
+ - target: miniapp
120
+ action: navigate
121
+ url: /pages/login/index
122
+ - target: miniapp
123
+ action: assert
124
+ dataPath: status
125
+ expected: ready
126
+ # 绕过原生授权弹窗,注入"用户拒绝"事件
127
+ - target: miniapp
128
+ action: trigger
129
+ locator: { css: ".login-btn" }
130
+ eventType: getphonenumber
131
+ detail: { code: "" }
132
+ - target: miniapp
133
+ action: assert
134
+ locator: { css: ".toast" }
135
+ expected: 重新选择
136
+ ```
137
+
138
+ 示例:callWxApi 造"未授权设备"前置 + 数量断言:
139
+
140
+ ```yaml
141
+ steps:
142
+ - target: miniapp
143
+ action: launch
144
+ - target: miniapp
145
+ action: callWxApi
146
+ wxApi: clearStorageSync # 制造未授权前置,替代"换设备"
147
+ - target: miniapp
148
+ action: navigate
149
+ url: /pages/list/index
150
+ - target: miniapp
151
+ action: assert
152
+ locator: { css: ".list-item" }
153
+ count: 0 # 未授权时列表为空
154
+ ```
48
155
 
49
156
  字段定义最终以 `packages/dsl` 的 zod schema 为准;不要使用表中之外的字段。
50
157
 
@@ -58,7 +165,7 @@ teardown: # 可选:setup 开始后始终执行
58
165
  - `${dataset.*}`:当前数据行
59
166
  - `${account.*}`:`accountRef` 对应凭据
60
167
  - `${variable.*}`:`testpilot.yaml variables` 白名单
61
- - `${name}`:之前 `extract` 产生的运行时变量
168
+ - `${name}`:之前 `extract` 产生的运行时变量(含 `callWxApi` 的 `variable` 捕获)
62
169
  - 禁止 `${env.*}` 或其他方式任意读取进程环境变量。
63
170
 
64
171
  `requires` 只检查路径存在且不是 `null`、空字符串或未解析的 `${ENV_VAR}`。缺失时该行不执行任何阶段,结果为 `skipped`,原因 `dependency-not-ready`。
@@ -90,7 +197,7 @@ setup 失败时主结果 failed、跳过主步骤并执行 teardown;主步骤失
90
197
  windowMs: 1000
91
198
  ```
92
199
 
93
- 它只观察并计数,不拦截、不修改响应。断言失败时报告实际次数和已脱敏的匹配 URL。
200
+ 它只观察并计数,不拦截、不修改响应。断言失败时报告实际次数和已脱敏的匹配 URL。小程序端通过临时 mock `wx.request` 实现,step 结束自动恢复。
94
201
 
95
202
  ## api 端(HTTP 接口测试与造数)
96
203
 
@@ -135,8 +242,9 @@ login / order / payment ❌ 业务动作不是 Action
135
242
  click / input / assert ✓ 由基础 Action 组合表达业务流程
136
243
  ```
137
244
 
138
- 登录、下单等业务流程由多个基础 Action 组合而成,不要设计业务 Action。
245
+ 登录、下单等业务流程由多个基础 Action 组合而成,不要设计业务 Action。小程序深度 action(callMethod/setData/mockWxApi 等)同样只表达测试原语——驱动页面、注入事件、拦截 API——不封装业务语义。
139
246
 
140
247
  ## 示例
141
248
 
142
- 见仓库 `examples/cases/order-create.yaml`(小程序下单 → Web 后台验证的黄金路径)。
249
+ - 仓库 `examples/cases/order-create.yaml`:小程序下单 → Web 后台验证的跨端黄金路径
250
+ - 仓库 `examples/cases/miniapp-deep.yaml`:小程序深度测试全景(mock/trigger/dataPath/count/longpress/scroll 等)
@@ -1,33 +1,33 @@
1
- # Workflow:创建测试 Case
2
-
3
- 输入:用户需求,或 `test-requirements-review` 产出的**测试点清单**(推荐先做需求评审)。
4
-
5
- 1. 尚无测试点清单时,先执行 `workflows/test-requirements-review.md`;已有清单则直接使用。
6
- 2. 阅读本 Skill:`rules/dsl.md`、`rules/case-design.md`、`rules/locator.md`。
7
- 3. 分析项目结构:确定被测端(miniapp / web)与业务入口页面。
8
- 4. 针对测试点收集证据(读代码 / DOM / 现有测试),确定业务路径:从入口到业务结果页的完整步骤。
9
- 5. 按 DSL 规范生成 Case,写入 `tests/e2e/cases/<case-id>.yaml`:
10
- - 一条 Case 覆盖一个测试点(或一组强关联测试点)
11
- - 多个测试点步骤完全一致、仅数据和预期不同,使用 `datasets` 形成 data-driven Case;否则保持独立 Case
12
- - Case 的 `description` 注明关联的测试点编号(如 `测试点: TP-001`),保持需求可溯源
13
- - 按评审产出的平台执行信息声明 `accountRef` / `workspace`;发现 `.env` 缺少某平台的地址或凭据变量时,向用户索取后写入 `.env`,**不写进 Case**
14
- - 从需求与项目证据中识别最小 `requires`;项目没有账号/优惠/PPM 等概念时不要生成对应依赖
15
- - 公共参数写入 `tests/e2e/data/` fixture;环境参数先加入 `testpilot.yaml variables` 白名单
16
- - 造数与清理使用 `setup` / `teardown`;UI 动作需验证接口调用次数时使用 `expectRequests`
17
- - 把该 Case 关联 TP 的每个 charter 视角写入 `tags`,与既有 tag(如 `smoke`)共存;一个 TP 多视角则多 tag。映射(视角定义见 `test-requirements-review` 步骤 6):
18
-
19
- | 评审视角 | case tag |
20
- | --- | --- |
21
- | persona | `charter:persona` |
22
- | 边界输入 | `charter:edge-input` |
23
- | 数字与文案 | `charter:numbers-copy` |
24
- | 状态恢复 | `charter:state-recovery` |
25
- | 错误路径 | `charter:error-path` |
26
-
27
- ```yaml
28
- tags: [smoke, charter:persona, charter:error-path]
29
- ```
30
- 6. 执行 `npx csspilot validate tests/e2e/cases/<case-id>.yaml`。
31
- 7. 校验失败则修复 Case 后重新 validate,直到通过。
32
-
33
- 禁止:跳过第 3-4 步直接生成 Case(AI 不能凭空生成测试)。
1
+ # Workflow:创建测试 Case
2
+
3
+ 输入:用户需求,或 `test-requirements-review` 产出的**测试点清单**(推荐先做需求评审)。
4
+
5
+ 1. 尚无测试点清单时,先执行 `workflows/test-requirements-review.md`;已有清单则直接使用。
6
+ 2. 阅读本 Skill:`rules/dsl.md`、`rules/case-design.md`、`rules/locator.md`。
7
+ 3. 分析项目结构:确定被测端(miniapp / web)与业务入口页面。
8
+ 4. 针对测试点收集证据(读代码 / DOM / 现有测试),确定业务路径:从入口到业务结果页的完整步骤。
9
+ 5. 按 DSL 规范生成 Case,写入 `tests/e2e/cases/<case-id>.yaml`:
10
+ - 一条 Case 覆盖一个测试点(或一组强关联测试点)
11
+ - 多个测试点步骤完全一致、仅数据和预期不同,使用 `datasets` 形成 data-driven Case;否则保持独立 Case
12
+ - Case 的 `description` 注明关联的测试点编号(如 `测试点: TP-001`),保持需求可溯源
13
+ - 按评审产出的平台执行信息声明 `accountRef` / `workspace`;发现 `.env.testing` 缺少某平台的地址或凭据变量时,向用户索取后写入 `.env.testing`,**不写进 Case**
14
+ - 从需求与项目证据中识别最小 `requires`;项目没有账号/优惠/PPM 等概念时不要生成对应依赖
15
+ - 公共参数写入 `tests/e2e/data/` fixture;环境参数先加入 `testpilot.yaml variables` 白名单
16
+ - 造数与清理使用 `setup` / `teardown`;UI 动作需验证接口调用次数时使用 `expectRequests`
17
+ - 把该 Case 关联 TP 的每个 charter 视角写入 `tags`,与既有 tag(如 `smoke`)共存;一个 TP 多视角则多 tag。映射(视角定义见 `test-requirements-review` 步骤 6):
18
+
19
+ | 评审视角 | case tag |
20
+ | --- | --- |
21
+ | persona | `charter:persona` |
22
+ | 边界输入 | `charter:edge-input` |
23
+ | 数字与文案 | `charter:numbers-copy` |
24
+ | 状态恢复 | `charter:state-recovery` |
25
+ | 错误路径 | `charter:error-path` |
26
+
27
+ ```yaml
28
+ tags: [smoke, charter:persona, charter:error-path]
29
+ ```
30
+ 6. 执行 `npx csspilot validate tests/e2e/cases/<case-id>.yaml`。
31
+ 7. 校验失败则修复 Case 后重新 validate,直到通过。
32
+
33
+ 禁止:跳过第 3-4 步直接生成 Case(AI 不能凭空生成测试)。
@@ -16,7 +16,7 @@ CLI → Case Loader → DSL Validator → Execution Engine → Adapter(Playwrigh
16
16
 
17
17
  - 只通过 testpilot CLI 执行测试,不要直接调用 playwright 或 wechat-devtools。
18
18
  - 被测服务需先就绪(如业务后端、本地页面服务),`navigate` 的相对 url 基于 testpilot.yaml 的 `web.baseUrl` 解析。
19
- - 环境变量来源:shell / CI secrets,或项目根目录 `.env` 文件(CLI 自动加载,真实环境变量优先);`.env` 含敏感信息,确认已加入 .gitignore。
19
+ - 环境变量来源:shell / CI secrets,或项目根目录 `.env.testing` 文件(CLI 自动加载,真实环境变量优先;刻意不读前端项目自身的 `.env`);`.env.testing` 含敏感信息,确认已加入 .gitignore。
20
20
  - Case 只能读取 `testpilot.yaml variables` 白名单映射后的 `${variable.*}`,不能直接访问任意环境变量。
21
21
  - 运行前按 dataset 行展开并预检 `requires`;依赖缺失的行显示 `skipped(dependency-not-ready)`,不是产品失败。
22
22
  - 每行按 setup → steps → teardown 执行;teardown warning 不改变主结果。
@@ -1,7 +1,7 @@
1
1
  # Workflow:测试需求评审(可测性评审 + 测试点分析)
2
2
 
3
3
  输入:需求文档 / PRD / 用户的一句话(如"帮我测试用户下单")。
4
- 产出:**原子规则清单** + **规则矩阵** + **测试点清单** + **视角覆盖表** + **QA → TestPilot Coverage Map** + **平台执行信息表** + 澄清问题 + 评审结论。测试点清单是 `create-case` 的正式输入。
4
+ 产出:**原子规则清单** + **规则矩阵** + **测试点清单** + **视角覆盖表** + **QA → TestPilot Coverage Map** + **平台执行信息表** + **环境与资料准备清单** + 澄清问题 + 评审结论。测试点清单是 `create-case` 的正式输入;环境与资料准备清单决定 Case 能否直接执行。
5
5
 
6
6
  ## 步骤
7
7
 
@@ -116,14 +116,14 @@
116
116
 
117
117
  | 平台 | 必须澄清 | 落地位置 |
118
118
  | --- | --- | --- |
119
- | web | 测试地址(baseUrl)+ 页面入口路由 + 登录角色 | `.env` 的 `WEB_BASE_URL` / `TEST_BASE_URL`;`accountRef` |
120
- | miniapp | 小程序项目路径 + 起始页面路由 + 登录角色(连哪个环境后端) | `.env` 的 `MINIAPP_PROJECT_PATH`;`accountRef` |
121
- | api | 服务 baseUrl + 鉴权方式(token / session)+ 账号角色 | `.env` 的 `API_BASE_URL`;`accountRef` |
119
+ | web | 测试地址(baseUrl)+ 页面入口路由 + 登录角色 | `.env.testing` 的 `WEB_BASE_URL` / `TEST_BASE_URL`;`accountRef` |
120
+ | miniapp | 小程序项目路径 + 起始页面路由 + 登录角色(连哪个环境后端) | `.env.testing` 的 `MINIAPP_PROJECT_PATH`;`accountRef` |
121
+ | api | 服务 baseUrl + 鉴权方式(token / session)+ 账号角色 | `.env.testing` 的 `API_BASE_URL`;`accountRef` |
122
122
 
123
123
  规则:
124
124
 
125
125
  - **登录角色**:每个平台确认用什么角色(普通用户 / 管理员 / 游客),映射为 `accountRef`(如 `admin` / `test-user`);真实凭据放 `TESTPILOT_ACCOUNT_<REF大写>` 环境变量或 Server Secrets,**禁止写进 Case**
126
- - **测试地址**:一律指向测试环境,写入 `.env`(如 `WEB_BASE_URL`);**禁止把内网 / 生产地址写进 Case 或 testpilot.yaml**
126
+ - **测试地址**:一律指向测试环境,写入 `.env.testing`(如 `WEB_BASE_URL`);**禁止把内网 / 生产地址写进 Case 或 testpilot.yaml**
127
127
  - **使用 Workspace 的项目**:以上信息应登记为 Workspace 的绑定(项目 → 环境),Case 用 `workspace: <名称>` 声明,不逐条硬编码
128
128
 
129
129
  ### 澄清问题示例(多平台需求)
@@ -131,11 +131,48 @@
131
131
  - Web 后台的测试地址是什么?订单查询页面的入口路由是?
132
132
  - 小程序连接哪个环境的后端?小程序项目目录在本机哪里?
133
133
  - 各平台分别用什么角色登录(普通用户 / 管理员)?该角色是否有完成流程所需的权限?
134
- - 这些地址和账号是否已写入 `.env`?缺哪个我来补?
134
+ - 这些地址和账号是否已写入 `.env.testing`?缺哪个我来补?
135
+
136
+ ## 环境与资料准备清单(固定产出,禁止省略)
137
+
138
+ 对每条测试点自问:**「执行这条 TP 之前,哪些值必须已经存在?」**——测试地址、登录账号、业务造数字段、前置状态,凡命中就必须在清单中登记一行。**禁止"写 Case 时再说"**:评审不定下来,执行层就是确定性缺口。
139
+
140
+ 每项资料按落点**三分类**,这是判定规则,不得凭感觉选:
141
+
142
+ | 落点 | 放什么 | 判定特征 | 例子 |
143
+ | --- | --- | --- | --- |
144
+ | `.env.testing` 变量 | 环境位:测试地址、小程序项目路径、Server 地址 | 与"人 / 机器 / 环境"相关,与具体业务数据无关 | `WEB_BASE_URL`、`MINIAPP_PROJECT_PATH` |
145
+ | `accountRef` | 账号角色(只登记角色名与用途;真实凭据走 `TESTPILOT_ACCOUNT_<REF>` 或 Server Secrets) | "以谁的身份执行" | `admin`(后台)、`test-user`(下单用户) |
146
+ | fixture / dataset 字段 | 业务造数:测试点依赖的数据及**字段名**、类型、来源 | 与业务数据本身相关(商品、订单、规则入参) | `fixture.product.styleNo`(后端造数接口生成) |
147
+
148
+ 模板(即使没有任何要准备的资料,**也必须输出本节**并写「无」,附一句依据;三类落点各成一表或合并为一表均可,列必须齐全):
149
+
150
+ ```markdown
151
+ ## 环境与资料准备清单
152
+
153
+ | TP | 需要的资料 | 落点 | 变量名 / 字段名 | 来源或生成方式 | 就绪状态 |
154
+ | --- | --- | --- | --- | --- | --- |
155
+ | TP-001 | 测试环境地址 | .env.testing | WEB_BASE_URL | 用户提供 | 已就绪 |
156
+ | TP-002 | vip 账号 | accountRef | vip-user | 用户提供凭据(TESTPILOT_ACCOUNT_VIP_USER) | 待补充 |
157
+ | TP-003 | 参与促销的商品 | fixture | fixture.product.styleNo | 后端造数接口 POST /test-support/products | 待补充 |
158
+
159
+ ## Missing data checklist
160
+ - [ ] TP-002: 提供 vip-user 凭据
161
+ - [ ] TP-003: 确认造数接口可用
162
+ ```
163
+
164
+ 规则:
165
+
166
+ - **业务造数一律进 fixture/dataset**(字段名随后写入 Case 的 `requires`),**环境位才进 `.env.testing`**,**身份一律 `accountRef`**——三者不得混放,同一项资料只能有一个落点。混放(如把商品编码塞进 env、把地址写成 fixture)是评审输出不稳定的直接来源。
167
+ - 来源不可知的资料(谁提供、怎么造不确定)必须同时进入澄清问题清单。
168
+ - 「就绪状态」只有两种:已就绪 / 待补充;待补充项必须出现在 Missing data checklist。
169
+ - 本节缺失或含未登记的必要资料时,不得给出评审结论(见铁律)。
135
170
 
136
171
  ## 铁律
137
172
 
138
173
  - 没有测试点清单,不要进入 `create-case`。
174
+ - 没有「环境与资料准备清单」一节,不得给出评审结论;空表也要输出(写「无」+ 依据)。
175
+ - 测试点依赖的资料(账号 / 造数字段 / 环境地址 / 前置状态)必须逐项登记落点:`.env.testing`(环境位)/ `accountRef`(身份)/ fixture-dataset(业务造数),禁止混放、禁止执行时再想。
139
176
  - 涉及多平台但执行信息(地址 / 入口 / 登录角色)不全时,结论只能是"有条件可测",先澄清再建 Case。
140
177
  - 评审基于需求 + 项目代码/页面证据;两项都没有时先收集证据,不空谈。
141
178
  - 每个测试点必须可验证:都能回答"怎么判定通过"。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "csspilot",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "description": "TestPilot — AI Native 跨端业务测试基础设施 CLI",
5
5
  "license": "MIT",
6
6
  "repository": {