software-design-test 1.2.0
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/CHANGELOG.md +63 -0
- package/LICENSE +21 -0
- package/README.md +275 -0
- package/cordis.patch.yml +23 -0
- package/docs/FRAMEWORK.zh-en.md +149 -0
- package/docs/INSTALL.zh-en.md +226 -0
- package/docs/USAGE.zh-en.md +295 -0
- package/icon.svg +21 -0
- package/lib/index.js +197 -0
- package/lib/self-check.js +313 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +80 -0
- package/scripts/capture.mjs +318 -0
- package/scripts/guard.mjs +311 -0
- package/scripts/report.mjs +484 -0
- package/scripts/session.mjs +709 -0
- package/scripts/verify.mjs +205 -0
- package/skills/observed-test-plan/MATRIX.md +99 -0
- package/skills/observed-test-plan/PERMISSIONS.md +109 -0
- package/skills/observed-test-plan/PLAN-TEMPLATE.md +93 -0
- package/skills/observed-test-plan/SKILL.md +135 -0
- package/skills/observed-ui-test/BANNED-INPUTS.md +161 -0
- package/skills/observed-ui-test/EVIDENCE.md +113 -0
- package/skills/observed-ui-test/FRAMEWORK.md +181 -0
- package/skills/observed-ui-test/LEVELS.md +137 -0
- package/skills/observed-ui-test/REPORT-TEMPLATE.md +111 -0
- package/skills/observed-ui-test/SKILL.md +210 -0
- package/skills/software-design-test/DEFECTS.md +205 -0
- package/skills/software-design-test/HEURISTICS.md +236 -0
- package/skills/software-design-test/PERSONAS-SCENARIOS.md +159 -0
- package/skills/software-design-test/SKILL.md +211 -0
- package/skills/software-design-test/SOURCES.md +118 -0
- package/skills/software-design-test/TEST-CONTENT.md +257 -0
- package/skills/software-design-test/WORKFLOW.md +293 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# 禁止使用的内在指针指令 / Banned Internal Pointer Directives
|
|
2
|
+
|
|
3
|
+
> **R1 是最高优先级的规则,任何级别(L1/L2/L3)都不放开。**
|
|
4
|
+
> **R1 outranks everything and is never relaxed, at any mode.**
|
|
5
|
+
>
|
|
6
|
+
> "内在指针指令"= 任何绕过人的真实外设、在程序内部合成指针/触摸/按键事件,或直接调用软件内部
|
|
7
|
+
> 句柄、接口、脚本来触发功能的指令。
|
|
8
|
+
> An "internal pointer directive" is any instruction that bypasses the human's real peripherals to
|
|
9
|
+
> synthesize a pointer, touch or key event inside the program, or that invokes the software's own
|
|
10
|
+
> internal handles, APIs or scripting to trigger a feature.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 一句话判据 / The one-line test
|
|
15
|
+
|
|
16
|
+
> 这条指令,是一个**人用手**就能做出来的动作吗?如果不是,或者它让软件在**没有人的手**参与下
|
|
17
|
+
> 动了,就不能用。
|
|
18
|
+
>
|
|
19
|
+
> Could a human produce this action with their hands? If not — or if it makes the software move with
|
|
20
|
+
> no human hand involved — it is banned.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 全平台通用禁止 / Banned everywhere
|
|
25
|
+
|
|
26
|
+
| 类别 Class | 例子 Examples |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| 指针/触摸/按键注入 | 合成鼠标移动、点击、触摸、滑动的任何 API |
|
|
29
|
+
| 自动化框架驱动 | 用测试框架把点击"打进"被应用(UI 自动化、录制回放、RPA、宏脚本) |
|
|
30
|
+
| 内部句柄调用 | 直接触发控件动作、调用应用内部命令、写数据库/配置文件来达到界面效果 |
|
|
31
|
+
| GUI 智能体代操作 | 任何"computer use / GUI agent"把鼠标键盘事件发给系统的能力 |
|
|
32
|
+
| 软件宏/脚本快捷键 | AutoHotkey 脚本、AppleScript 按键脚本、键盘宏软件(硬件宏需申报,见下) |
|
|
33
|
+
| 用代码"证明"UI | 打开 DOM 检查器/调试器/代码来判定界面是否正确(这会破坏 R2 的证据链) |
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## macOS
|
|
38
|
+
|
|
39
|
+
**禁止 / Banned**
|
|
40
|
+
|
|
41
|
+
| 指令 Directive | 为什么 Why |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| `CGEventCreateMouseEvent` / `CGEventPost` / `CGEventPostToPid` | 内核事件注入,合成点击 |
|
|
44
|
+
| `CGWarpMouseCursorPosition` / `CGAssociateMouseAndMouseCursorPosition` | 程序移动光标 |
|
|
45
|
+
| `IOHIDPostEvent` / `hidutil`(用于发事件时) | HID 层注入 |
|
|
46
|
+
| `cliclick`、`mouseclick`、`xdotool` 类工具 | 命令行合成输入 |
|
|
47
|
+
| `osascript -e 'tell application "System Events" to click at {x, y}'` | 系统级合成点击 |
|
|
48
|
+
| `System Events` 的 `keystroke` / `key code` / `perform action "AXPress"` | 合成按键与内部动作调用 |
|
|
49
|
+
| Accessibility API:`AXUIElementPerformAction(kAXPressAction)` | 直接调用控件内部动作 |
|
|
50
|
+
| XCTest / XCUITest:`XCUIElement.tap()`、`typeText()` | 测试框架合成触摸 |
|
|
51
|
+
| `osascript -e 'tell application "App" to ...'` 触发业务功能 | 调用应用内部脚本接口代替界面操作 |
|
|
52
|
+
| 浏览器 DOM:`el.click()`、`dispatchEvent(new MouseEvent(...))`、CDP `Input.dispatchMouseEvent`、Playwright/Puppeteer/Selenium 的 `click()` | 绕过真实指针 |
|
|
53
|
+
|
|
54
|
+
**允许 / Allowed**
|
|
55
|
+
|
|
56
|
+
- 人用鼠标、触控板、外接键盘操作;人用手指/触控笔在 iPhone/iPad 上操作。
|
|
57
|
+
- 只读捕获:`screencapture -x`(截屏)、`screencapture -v`(录屏)、QuickTime 录屏、OBS 录屏。
|
|
58
|
+
- 只读观测线索:日志窗口、活动监视器(只作为线索,不能作为结论)。
|
|
59
|
+
- 环境准备(测试开始**前**完成,并在报告里记录):切换深色模式、分辨率、缩放、辅助功能键盘。
|
|
60
|
+
- `osascript` 读取窗口标题/版本号等**环境元数据**可以,但不得用于触发任何功能。
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Windows
|
|
65
|
+
|
|
66
|
+
**禁止 / Banned**
|
|
67
|
+
|
|
68
|
+
| 指令 Directive | 为什么 Why |
|
|
69
|
+
| --- | --- |
|
|
70
|
+
| `SendInput` / `mouse_event` / `keybd_event` | Win32 合成输入 |
|
|
71
|
+
| `SetCursorPos` | 程序移动光标 |
|
|
72
|
+
| `PostMessage` / `SendMessage` 发 `WM_LBUTTONDOWN`、`WM_COMMAND`、`WM_KEYDOWN` | 直接给窗口投递内部消息 |
|
|
73
|
+
| UI Automation `InvokePattern.Invoke()` / `TogglePattern` / `SetValue` | 调用控件内部动作 |
|
|
74
|
+
| PowerShell `[System.Windows.Forms.SendKeys]::SendWait()`、`[System.Windows.Forms.Cursor]::Position`、`WScript.Shell SendKeys` | 脚本合成输入 |
|
|
75
|
+
| AutoHotkey / RPA / WinAppDriver / Appium Windows 驱动 | 自动化框架驱动界面 |
|
|
76
|
+
| `nircmd`、宏软件 | 合成输入 |
|
|
77
|
+
|
|
78
|
+
**允许 / Allowed**
|
|
79
|
+
|
|
80
|
+
- 人用鼠标与键盘操作。
|
|
81
|
+
- 只读捕获:Xbox Game Bar(`Win+G`,由人手动按)、OBS、Windows 截图工具、PowerShell 的
|
|
82
|
+
`System.Drawing` 只读截屏(`capture.mjs` 走这条路)。
|
|
83
|
+
- 环境准备(测试前):缩放比例、深浅色、区域设置。
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## iPhone / iPad(iOS / iPadOS)
|
|
88
|
+
|
|
89
|
+
**禁止 / Banned**
|
|
90
|
+
|
|
91
|
+
| 指令 Directive | 为什么 Why |
|
|
92
|
+
| --- | --- |
|
|
93
|
+
| XCUITest `XCUIElement.tap()` / `typeText()` / 录制回放 | 合成触摸 |
|
|
94
|
+
| `idb ui tap` / `fb-idb` / Appium / WebDriverAgent | 合成触摸与按键 |
|
|
95
|
+
| 任何"远程控制设备"工具用脚本注入触摸(含 scrcpy 类工具的控制模式) | 合成触摸 |
|
|
96
|
+
| 用 `simctl` 修改应用内部状态来"制造"通过结果 | 内部句柄调用 |
|
|
97
|
+
|
|
98
|
+
**允许 / Allowed**
|
|
99
|
+
|
|
100
|
+
- 人用手指、触控笔、外接键盘鼠标在真机上操作。
|
|
101
|
+
- 模拟器:人用**真实鼠标**点击模拟器窗口(这是真实指针,不是注入)。
|
|
102
|
+
- 只读捕获:`xcrun simctl io booted screenshot` / `recordVideo`、控制中心的屏幕录制、
|
|
103
|
+
QuickTime + 连续互通录制真机屏幕。
|
|
104
|
+
- 环境准备(测试前,写进报告):`xcrun simctl` 设定外观明暗、语言区域、状态栏覆盖、
|
|
105
|
+
启动/安装被测应用、`simctl openurl` 建立前置页面。**这些只用于建立前置状态,
|
|
106
|
+
测试过程中不得用来代替人在界面上的操作。**
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 其他交互设备 / Other interactive devices
|
|
111
|
+
|
|
112
|
+
| 设备 Device | 禁止 Banned | 允许 Allowed |
|
|
113
|
+
| --- | --- | --- |
|
|
114
|
+
| Android 手机/平板 | `adb shell input tap/swipe/text/keyevent`、`monkey`、uiautomator、Espresso、Appium、scrcpy 控制模式 | 手指操作;`adb exec-out screencap -p` 只读截屏;`screenrecord` 只读录屏 |
|
|
115
|
+
| 电视/车机/手表 | 任何 SDK 注入遥控或触摸事件的接口 | 人用真实遥控器/触摸/旋钮操作;只读投屏与截屏 |
|
|
116
|
+
| 网页应用 | `el.click()`、合成事件、浏览器自动化框架 | 人用真实鼠标键盘;只读截屏工具 |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 硬件宏与"看起来合规"的灰色地带 / Grey areas
|
|
121
|
+
|
|
122
|
+
| 情况 Case | 结论 Verdict |
|
|
123
|
+
| --- | --- |
|
|
124
|
+
| 硬件宏键盘(宏在键盘固件里,发出真实 HID 事件) | **可以,但必须在报告里申报**:它降低了"人手操作"的证据强度 |
|
|
125
|
+
| 软件宏(AutoHotkey、BetterTouchTool 宏、脚本快捷键) | **禁止** |
|
|
126
|
+
| 无障碍"鼠标键""粘滞键"等由人操作的系统辅助 | 可以,需申报;它们改变的是人的操作方式,不是注入 |
|
|
127
|
+
| 录屏软件自带的"点击高亮/自动操作"叠加功能 | 高亮可以,自动操作禁止 |
|
|
128
|
+
| 用剪贴板预置内容 + 菜单粘贴 | 在 L1 允许,剪贴板内容必须在测试前由人准备 |
|
|
129
|
+
| 用开发者工具/代码判断界面是否正确 | 禁止作为结论;可作为怀疑线索,但必须用画面确认 |
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 违规自检 / Self-check before you start
|
|
134
|
+
|
|
135
|
+
1. 被测机器上是否开着自动化工具、宏软件、按键精灵类程序?→ 全部退出。
|
|
136
|
+
2. macOS 的"辅助功能"权限是否给了任何非必要应用?→ 收回(本方法不需要辅助功能权限)。
|
|
137
|
+
3. 浏览器是否开着自动化调试端口/自动化扩展?→ 关闭。
|
|
138
|
+
4. 会话计划里是否出现了被禁指令的名字?→ 删掉,改写成人的操作步骤。
|
|
139
|
+
5. 插件的脚本是否只做只读捕获?→ `node scripts/verify.mjs` 会自动扫一遍,
|
|
140
|
+
确保包内不存在被禁的输入 API。
|
|
141
|
+
|
|
142
|
+
If any automation tool, macro utility or accessibility control grant is active, close it first. This
|
|
143
|
+
method needs **capture** permission only — never control/injection permission.
|
|
144
|
+
|
|
145
|
+
## 让守门器替你盯 / Let the watchdog watch
|
|
146
|
+
|
|
147
|
+
"我们没用注入"这句话,要让机器留痕,而不是靠自觉。插件自带 `guard.mjs`,
|
|
148
|
+
它**观察**注入指令、从不**执行**注入(纯只读进程表扫描 + 文本扫描):
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
node scripts/guard.mjs scan <session> # 测试前:扫描 + 落盘
|
|
152
|
+
node scripts/guard.mjs watch <session> --seconds 600 # 测试中:后台盯着
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
- 命中会写进 `evidence/compliance.jsonl`,并在报告第 8 节汇总。
|
|
156
|
+
- 它同时扫描 `matrix.md` / `elements.md` / `findings.jsonl`,若步骤里写了被禁指令名字,会直接标出来。
|
|
157
|
+
- 它只能给出线索,不能证明"绝对没有注入";有线索时人工确认,并**重跑受影响的用例**。
|
|
158
|
+
|
|
159
|
+
Let the machine leave a trace instead of trusting good intentions. `guard.mjs` observes injection
|
|
160
|
+
directives and never performs one; hits land in `evidence/compliance.jsonl` and in section 8 of the
|
|
161
|
+
report. It produces leads, not proof of absence — confirm by hand and re-run affected cases.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# 取证协议 / Evidence Protocol
|
|
2
|
+
|
|
3
|
+
> 画面是唯一证据。取证的目标不是"拍下来",是"让另一个人看到你看到的那个元素"。
|
|
4
|
+
> The picture is the only evidence. The goal is not "take a picture" — it is "let another person see
|
|
5
|
+
> the element you saw".
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. 两种证据 / Two kinds
|
|
10
|
+
|
|
11
|
+
| 类型 Kind | 用途 Use | 要求 Requirement |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| 屏幕录制 Screen recording | 过程、时序、反馈、动效、卡顿、误触发 | 连续、含光标、含系统时间;操作者口述动作与时间点 |
|
|
14
|
+
| 截屏 Screenshot | 单点状态、元素细节、对比(前/后、L1/L2/L3) | 含窗口全貌与系统时间;必要时再拍一张放大局部 |
|
|
15
|
+
|
|
16
|
+
**录屏与截屏至少要有一个**,否则本方法无法进行(无画面 = 无证据 = 只能记为未验证)。
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 2. 命名与时间 / Naming and time
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
evidence/<UTC或本地时间>-<用例ID>-<级别>-<前|后|异常>-<平台>.png
|
|
24
|
+
例:evidence/2026-10-04T093012-L1-07-L1-after-macos.png
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
- 一条缺陷至少一张图;跨模式差异至少两张(不同级别的同一状态)。
|
|
28
|
+
- 录屏要记住时间点(`mm:ss`),写进缺陷的"证据"字段。
|
|
29
|
+
- 报告里引用证据时用**相对路径**,方便整个会话目录一起交付。
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 3. 一张合格的截图 / What a usable screenshot must show
|
|
34
|
+
|
|
35
|
+
- **完整上下文**:看得见窗口标题、所在界面、周围的关键控件。
|
|
36
|
+
- **元素本身**:要看的是哪个按钮/输入框/列表,就在画面里清晰可辨(必要时补一张局部特写)。
|
|
37
|
+
- **状态可见**:悬停态、焦点环、禁用态、错误提示——要拍到它们**出现的那一刻**。
|
|
38
|
+
- **时间可见**:菜单栏时钟或状态栏时间在画面内。
|
|
39
|
+
- **不含敏感信息**:真实姓名、手机号、邮箱、密钥、生产数据要打码或改用测试数据。
|
|
40
|
+
|
|
41
|
+
**不合格 / Rejected**:只有一行报错文字没有界面;只拍了一角不知道是哪个界面;
|
|
42
|
+
照片糊到看不清字形;用代码截图(终端里的 HTML/JSON)冒充界面证据。
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 3.5 采样纪律 / Sampling discipline
|
|
47
|
+
|
|
48
|
+
**只靠固定间隔看画面,一定会漏掉一闪而过的状态**(toast、短暂错误、瞬间的禁用态)。
|
|
49
|
+
GUI 智能体的"截图翻页"方法有同样的已知盲区。所以:
|
|
50
|
+
|
|
51
|
+
- 全程录屏 + **每次点击前后各补一张静帧**(事件触发采样)。
|
|
52
|
+
- 关键状态(加载、成功、错误、禁用)出现时立刻截图,不要等它消失。
|
|
53
|
+
- 用屏幕阅读器时,**记录"听到什么"**——有些缺陷在画面上不可见、在耳朵里才成立。
|
|
54
|
+
|
|
55
|
+
> Fixed-rate recording plus event-triggered stills around every click. Record what is **heard** as
|
|
56
|
+
> well as what is seen; a defect can be invisible on screen and obvious in the ear.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 4. 只用什么工具取证 / Capture tooling that is allowed
|
|
61
|
+
|
|
62
|
+
只读捕获,永远不注入输入 / read-only capture only:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
node scripts/capture.mjs check # 看本机有哪些只读捕获工具
|
|
66
|
+
node scripts/capture.mjs shot <session> --label L1-07-after
|
|
67
|
+
node scripts/capture.mjs record <session> --label L1 --seconds 60
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
- macOS:`screencapture -x`(静默截屏)、`screencapture -v`(录屏,可含光标)
|
|
71
|
+
- Windows:只读截屏(PowerShell `System.Drawing`)、Xbox Game Bar / OBS 录屏(人手动触发)
|
|
72
|
+
- iPhone/iPad:`xcrun simctl io booted screenshot|recordVideo`、控制中心屏幕录制、
|
|
73
|
+
QuickTime 连续互通(真机)
|
|
74
|
+
- Android:`adb exec-out screencap -p`、`adb shell screenrecord`
|
|
75
|
+
|
|
76
|
+
**取证期间**:录制屏幕本身就要求系统权限,见 `observed-test-plan` 的 `PERMISSIONS.md`。
|
|
77
|
+
录屏若不含光标,必须额外用截屏记录指针位置,并在报告里注明"录屏无光标"。
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 5. 观察者怎么读图 / How the observer reads a picture
|
|
82
|
+
|
|
83
|
+
Agent 用 `read_image` 打开截图,然后**逐元素描述你实际看到的像素**:
|
|
84
|
+
|
|
85
|
+
1. 这是什么界面?标题栏写了什么?
|
|
86
|
+
2. 清单里的每个元素:在不在?长什么样?有没有异常(破图、错位、缺字、被裁、重叠)?
|
|
87
|
+
3. 状态:哪个元素是选中的?焦点环在哪?有没有错误提示?文字写的是什么?
|
|
88
|
+
4. 与期望的差异:差在哪,用画面上可指认的位置描述("右上角齿轮按钮的图标缺失,只剩一块灰底")。
|
|
89
|
+
|
|
90
|
+
描述纪律 / Discipline:
|
|
91
|
+
- 不写"应该是"、"大概"、"通常";写"图中可见 / 图中不可见"。
|
|
92
|
+
- 看不清就说看不清,标为"证据不足",不要补脑。
|
|
93
|
+
- 不把日志或代码结论写进画面观察结论里。
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 6. 证据不足时 / When evidence is insufficient
|
|
98
|
+
|
|
99
|
+
| 情形 Case | 处理 Action |
|
|
100
|
+
| --- | --- |
|
|
101
|
+
| 图糊/被裁 | 重拍,或补拍特写;重拍不了就标"证据不足" |
|
|
102
|
+
| 现象一闪而过 | 用录屏 + 慢放定位,或让操作者复现一次再拍 |
|
|
103
|
+
| 权限不允许录屏 | 用法逐步截屏替代,报告首页写明"无连续录屏" |
|
|
104
|
+
| 现象无法复现 | 记"疑点(待复现)"并写出怀疑依据与当时的观察 |
|
|
105
|
+
| 只能看到结果看不到过程 | 明确写"结果可见,过程未观察到" |
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 7. 留证边界 / Boundaries
|
|
110
|
+
|
|
111
|
+
- 证据只存本次会话目录,不外传;交付时整目录给用户。
|
|
112
|
+
- 涉密/隐私内容默认不录;必须先问用户哪些界面不能录。
|
|
113
|
+
- 录屏文件可能很大,会话结束前问用户是保留原视频还是只留关键帧。
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# 观察式界面测试框架 / The Observed UI Testing Framework
|
|
2
|
+
|
|
3
|
+
> 从上到下的设计:先定立场,再定闸门、范围、清单、矩阵、执行、取证、判定、报告。
|
|
4
|
+
> Top-down design: position first, then gate, scope, inventory, matrix, execution, evidence,
|
|
5
|
+
> adjudication, report.
|
|
6
|
+
>
|
|
7
|
+
> 本文是 [SKILL.md](SKILL.md) 的展开版。/ This file expands [SKILL.md](SKILL.md).
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 层 0 · 立场 / Layer 0 · Position
|
|
12
|
+
|
|
13
|
+
| 角色 Role | 是谁 Who | 职责 Responsibility |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| 操作者 Operator | 用户(人) | 用真实鼠标键盘操作被测软件,是**唯一的手** |
|
|
16
|
+
| 观察者 Observer | Agent + 用户 | 看录屏/截屏,判读元素与工具状态,是**眼睛** |
|
|
17
|
+
| 记录者 Recorder | Agent | 写用例、记证据、出报告,是**笔** |
|
|
18
|
+
| 裁决者 Adjudicator | 用户 | 确认严重级、确认是否算缺陷、决定修不修 |
|
|
19
|
+
|
|
20
|
+
Agent 不能自己动鼠标、不能自己按键、不能注入事件。Agent 能做的是:
|
|
21
|
+
**生成用例与清单、驱动只读的截屏/录屏、读图判读、写报告。**
|
|
22
|
+
|
|
23
|
+
The agent never moves the mouse, never presses a key, never injects an event. What it does:
|
|
24
|
+
generate cases and inventory, drive read-only capture, read the pictures, write the report.
|
|
25
|
+
|
|
26
|
+
三条不可交换的原则 / Three non-negotiables:
|
|
27
|
+
|
|
28
|
+
1. **真实输入 / Real input** — 输入只来自人的外设。
|
|
29
|
+
2. **画面证据 / Visual evidence** — 结论必须有对应的画面。
|
|
30
|
+
3. **可复现 / Reproducible** — 每条结论都能被另一个操作者按步骤重放。
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 层 1 · 权限闸门 / Layer 1 · Permission gate
|
|
35
|
+
|
|
36
|
+
进入测试的充要条件 / The entry condition:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
gate.confirmed = mouse ∧ keyboard(级别已定) ∧ (screenRecording ∨ screenshot) ∧ scopeAcknowledged
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- 用户逐项回答,答案落盘到 `session.json`。
|
|
43
|
+
- `screenRecording` 与 `screenshot` 至少要有一个为真,否则**无法进行观察式测试**,直接停止并说明原因。
|
|
44
|
+
- 拒绝项不是"小问题":它是覆盖率的缺口,必须出现在报告首页。
|
|
45
|
+
- 平台侧权限清单见 `observed-test-plan` 技能的 `PERMISSIONS.md`。
|
|
46
|
+
|
|
47
|
+
Details per platform live in the companion skill's `PERMISSIONS.md`. A denied item is never papered
|
|
48
|
+
over; it becomes a coverage gap on page one of the report.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 层 2 · 范围 / Layer 2 · Scope
|
|
53
|
+
|
|
54
|
+
写死这六项,缺一项后面就会写出无法复现的缺陷 / Pin these six, or the later defects will not
|
|
55
|
+
reproduce:
|
|
56
|
+
|
|
57
|
+
1. 被测应用名 + 版本 + 构建号 / app, version, build
|
|
58
|
+
2. 平台与设备 / platform and device(macOS 版本 / Windows 版本 / iPhone 型号 + iOS 版本 / iPad + iPadOS 版本)
|
|
59
|
+
3. 输入设备 / input devices(鼠标型号、触控板、键盘布局;iPhone/iPad 是手指、触控笔还是外接键鼠)
|
|
60
|
+
4. 显示环境 / display(分辨率、缩放、外接屏、深色模式、动态字体大小)
|
|
61
|
+
5. 数据边界 / data boundary(用哪个账号、哪些数据不可触碰、是否需要脱敏)
|
|
62
|
+
6. 退出条件 / exit criteria(什么情况立刻停:崩溃、数据损坏、隐私泄露)
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 层 3 · 元素清单 / Layer 3 · Element inventory
|
|
67
|
+
|
|
68
|
+
**只看画面**建立清单:打开软件,逐个界面截图,把看得见的功能元素与工具抄下来。
|
|
69
|
+
不许打开代码、DOM 检查器或数据库来"补全"清单——那会让测试变成"验证我读到的代码"。
|
|
70
|
+
|
|
71
|
+
Build the inventory **from the screen only**: open the app, screenshot each surface, transcribe the
|
|
72
|
+
visible elements and tools. Do not open code, a DOM inspector or a database to "complete" the
|
|
73
|
+
inventory: that turns testing into "verifying the code I just read".
|
|
74
|
+
|
|
75
|
+
清单条目建议字段 / Suggested fields:
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
ID | 界面 Surface | 元素/工具 Element or tool | 类型 Type | 期望状态 Expected states | 优先级 Priority
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
类型 Type:`按钮 button` · `输入框 field` · `菜单/工具栏 menu/toolbar` · `列表/表格 list/table` ·
|
|
82
|
+
`滚动区 scroll area` · `弹窗/面板 dialog/panel` · `开关/选择器 toggle/picker` · `状态/提示 status/toast` ·
|
|
83
|
+
`画布/工具 canvas/tool` · `导航 navigation`。
|
|
84
|
+
|
|
85
|
+
期望状态 Expected states 至少写全:默认、悬停、按下、选中、禁用、加载、错误、空。
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 层 4 · 用例矩阵 / Layer 4 · Case matrix
|
|
90
|
+
|
|
91
|
+
矩阵 = 元素 × 平台 × 模式。允许裁剪,但裁剪要写理由。
|
|
92
|
+
|
|
93
|
+
Matrix = element × platform × mode. Trimming is allowed; the reason is not optional.
|
|
94
|
+
|
|
95
|
+
```text
|
|
96
|
+
用例 ID | 元素 | 前置条件 | 操作步骤(该模式下) | 期望结果(画面上可见) | 平台 | 模式 L1/L2/L3 | 优先级
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
优先级 Priority:
|
|
100
|
+
**P0** 主流程 / primary flow · **P1** 常用功能与数据正确性 · **P2** 边缘与异常(空、超长、断网、权限不足) ·
|
|
101
|
+
**P3** 打磨与一致性。
|
|
102
|
+
|
|
103
|
+
规则 / Rules:
|
|
104
|
+
- 同一个用例在 L1、L2、L3 各跑一次,步骤写法按该模式调整(L1 里不能出现 Tab)。
|
|
105
|
+
- 每条用例的"期望结果"必须是**画面上能看到的东西**,不能是"数据库里多一行"。
|
|
106
|
+
- P2 用例至少覆盖:空输入、超长输入、无权限、离线、快速重复点击、窗口/屏幕旋转。
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 层 5 · 三级执行 / Layer 5 · Three-mode execution
|
|
111
|
+
|
|
112
|
+
严格顺序 L1 → L2 → L3,中间不混用输入。/ Strictly L1 → L2 → L3, never mixed.
|
|
113
|
+
|
|
114
|
+
执行时的纪律 / Discipline while running:
|
|
115
|
+
|
|
116
|
+
- 一次只改一个变量:先不改设置、不改窗口大小,跑完基线再测边缘。
|
|
117
|
+
- 每条用例前后各截一张图(前:前置状态;后:结果状态)。
|
|
118
|
+
- 出现异常先**别修**,先截图,再决定是否继续——修了就没证据了。
|
|
119
|
+
- 操作者报出动作与时间点(例如"14:32 点了右上角齿轮"),观察者据此在录屏里定位。
|
|
120
|
+
- Agent 每个用例结束时立刻落盘 `findings.jsonl`,别攒到最后回忆。
|
|
121
|
+
|
|
122
|
+
Per case: screenshot before and after; when something looks wrong, capture first and do not fix it;
|
|
123
|
+
the operator narrates action + timestamp; the agent writes each finding to disk immediately.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 层 6 · 取证 / Layer 6 · Evidence
|
|
128
|
+
|
|
129
|
+
协议见 [EVIDENCE.md](EVIDENCE.md)。最低要求 / Minimum:
|
|
130
|
+
每条结论一条证据,文件名含用例 ID 与时间点,证据能读出**元素本身**而不是一堆背景。
|
|
131
|
+
|
|
132
|
+
除画面证据外,还有一类**合规证据**:`guard.mjs` 的只读观察日志
|
|
133
|
+
(`evidence/compliance.jsonl`),记录观察期间是否出现疑似注入线索、测试文本里是否写了被禁指令。
|
|
134
|
+
它观察注入、从不执行注入;它给的是线索而非"绝对没有注入"的证明。
|
|
135
|
+
Alongside visual evidence there is **compliance evidence**: the read-only watchdog log from
|
|
136
|
+
`guard.mjs`. It observes injection, never performs it, and yields leads rather than proof of absence.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 层 7 · 判定 / Layer 7 · Adjudication
|
|
141
|
+
|
|
142
|
+
一条发现只允许落成四类之一 / Every observation becomes exactly one of:
|
|
143
|
+
|
|
144
|
+
| 类别 Kind | 含义 Meaning | 处理 Action |
|
|
145
|
+
| --- | --- | --- |
|
|
146
|
+
| 缺陷 Defect | 可复现、有画面证据、期望与实际不符 | 进缺陷表,定 S1–S4 |
|
|
147
|
+
| 观察 Observation | 现象为真,但不确定是否违背设计意图 | 写清现象与影响,交用户裁决 |
|
|
148
|
+
| 疑点 Suspicion | 像是问题但没复现出来 | 标"待复现"并写出怀疑依据 |
|
|
149
|
+
| 未验证 Unverified | 证据不足或权限缺失 | 写原因,不许写成通过 |
|
|
150
|
+
|
|
151
|
+
三级模式差异的判定句式 / Sentence patterns for cross-mode differences:
|
|
152
|
+
|
|
153
|
+
- 「L1 做不到,L2/L3 能做到」→ **缺鼠标可达路径**(可用性/无障碍缺陷)。
|
|
154
|
+
- 「L1/L2 能做到,L3 失败」→ **快捷键路径缺陷**。
|
|
155
|
+
- 「三级都做不到」→ **功能本身缺陷**。
|
|
156
|
+
- 「L1 出现,L2/L3 不出现」→ **与输入方式耦合的状态缺陷**(例如悬停态残留)。
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 层 8 · 报告与修复 / Layer 8 · Report and fix
|
|
161
|
+
|
|
162
|
+
用 [REPORT-TEMPLATE.md](REPORT-TEMPLATE.md)。至少给用户三样东西 / Deliver at least three things:
|
|
163
|
+
|
|
164
|
+
1. 能照着复现的缺陷表 / a reproducible defect table
|
|
165
|
+
2. 覆盖了什么、没覆盖什么、为什么 / what was and was not covered, and why
|
|
166
|
+
3. 建议的修复顺序(S1 先行,同因合并)/ a fix order, S1 first, same root cause merged
|
|
167
|
+
|
|
168
|
+
修复后必须**用同一个用例、同一个模式**复测,并把复测结论追加到原缺陷条目,而不是新开一条。
|
|
169
|
+
After a fix, retest with the same case in the same mode and append the result to the original entry.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 原语 / Primitives
|
|
174
|
+
|
|
175
|
+
步骤只用这些词,避免歧义 / Write steps with these verbs only:
|
|
176
|
+
|
|
177
|
+
移动 move · 悬停 hover · 单击 click · 双击 double-click · 右键 right-click · 拖拽 drag ·
|
|
178
|
+
滚轮 scroll · 键入 type · 焦点移动 focus next/previous · 等待 wait(写明确切秒数或等待什么出现)。
|
|
179
|
+
|
|
180
|
+
不许出现"调用接口 xxx""通过脚本点击""执行内部命令"这类描述——那正是 R1 禁止的东西。
|
|
181
|
+
Phrases like "call endpoint x", "click via script", "run internal command" are exactly what R1 bans.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# 三级操作模式 / The Three Input Modes
|
|
2
|
+
|
|
3
|
+
> L1 仅鼠标 → L2 鼠标+键盘(禁快捷键)→ L3 鼠标+键盘+快捷键。
|
|
4
|
+
> Mouse only → mouse + keyboard without shortcuts → with shortcuts.
|
|
5
|
+
>
|
|
6
|
+
> 每一级都要跑**同一批用例**。差异就是结论。/ Run the same cases at every level. The difference
|
|
7
|
+
> is the finding.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## L1 · 仅鼠标 / Mouse only
|
|
12
|
+
|
|
13
|
+
**允许 Allowed**
|
|
14
|
+
|
|
15
|
+
| 动作 Action | 说明 Notes |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| 移动、悬停 move / hover | 含等待悬停提示出现 |
|
|
18
|
+
| 单击、双击 click / double-click | 左右键都算 |
|
|
19
|
+
| 右键与上下文菜单 right-click / context menu | 上下文菜单是鼠标路径的一部分 |
|
|
20
|
+
| 拖拽 drag | 含拖到边缘、拖出窗口、拖到无效区域 |
|
|
21
|
+
| 滚轮/触控板滚动 scroll | 含横向滚动、惯性滚动 |
|
|
22
|
+
| 菜单栏与工具栏点击 menu bar / toolbar click | 走菜单完成命令 |
|
|
23
|
+
| 用「编辑 → 粘贴」配合**测试前已预置**的剪贴板 | 剪贴板内容由操作者在测试前准备好,L1 期间不再改动 |
|
|
24
|
+
| 屏幕键盘(若已开启)on-screen keyboard | 用鼠标点屏上按键;开启动作在测试前完成并记录 |
|
|
25
|
+
| iPhone/iPad 上的手指/触控笔操作 | 手指就是手指;模拟器上则是真实鼠标点击模拟器窗口 |
|
|
26
|
+
|
|
27
|
+
**禁止 Forbidden**
|
|
28
|
+
|
|
29
|
+
- 任何物理键盘输入,包括 Tab 焦点导航、方向键、Enter。
|
|
30
|
+
- 一切修饰键组合。
|
|
31
|
+
- 内部指针指令(R1 永久生效)。
|
|
32
|
+
- 用剪贴板以外的"系统侧注入"来填内容。
|
|
33
|
+
|
|
34
|
+
**能抓到的缺陷 / Defects this level catches**
|
|
35
|
+
|
|
36
|
+
- 功能只能靠快捷键或键盘才能到达(无鼠标可达路径)。
|
|
37
|
+
- 命中区域小于视觉外观,或视觉上像按钮实际不可点。
|
|
38
|
+
- 必须悬停才可发现的控件在触屏/无悬停设备上不可用。
|
|
39
|
+
- 上下文菜单缺项、菜单项灰掉且无解释。
|
|
40
|
+
- 滚动容器卡住、拖拽无反馈、拖拽后状态回弹。
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## L2 · 鼠标 + 键盘,禁止快捷键 / Mouse + keyboard, no shortcuts
|
|
45
|
+
|
|
46
|
+
**允许 Allowed(在 L1 之上新增)**
|
|
47
|
+
|
|
48
|
+
| 键 Keys | 允许原因 Why |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| 字母/数字/符号输入 character input | 这是"输入",不是捷径 |
|
|
51
|
+
| Enter / Return | 表单提交的基础路径 |
|
|
52
|
+
| Tab / Shift+Tab | 焦点导航本身就是要测的对象 |
|
|
53
|
+
| 方向键 arrows | 列表与光标导航 |
|
|
54
|
+
| Backspace / Delete | 编辑文本 |
|
|
55
|
+
| 空格 space | 文本输入与(在有焦点时)激活控件 |
|
|
56
|
+
| Home / End / PageUp / PageDown | 视图导航,不触发命令 |
|
|
57
|
+
| Shift(仅用于输入大写字母与上档符号) | 不触发命令 |
|
|
58
|
+
|
|
59
|
+
**禁止 Forbidden(在 L1 的基础之上新增)**
|
|
60
|
+
|
|
61
|
+
- 一切修饰键组合:`⌘/Cmd`、`Ctrl`、`⌥/Option/Alt`、`Win`、`Shift+字母` 以外的组合,
|
|
62
|
+
例如 ⌘C、⌘V、⌘S、⌘Z、Ctrl+F、Shift+点击(若该软件把它定义为命令)。
|
|
63
|
+
- 功能键 `F1`–`F12`(含"帮助""重命名""刷新"等)。
|
|
64
|
+
- 把 `Esc` 当作"取消/关闭/退出"的命令加速键使用。
|
|
65
|
+
- 仍然禁止内部指针指令。
|
|
66
|
+
|
|
67
|
+
> 边界说明 / Boundary note:`Shift+点击` 这类**指针手势**是否允许由测试计划预设并写清。
|
|
68
|
+
> 默认在 L2 允许(它一般不触发命令),在报告里注明即可。
|
|
69
|
+
> Whether a modifier + pointer gesture counts as a shortcut is decided in the plan and written down.
|
|
70
|
+
> Default: allowed at L2 because it usually triggers no command.
|
|
71
|
+
|
|
72
|
+
**能抓到的缺陷 / Defects this level catches**
|
|
73
|
+
|
|
74
|
+
- 键盘导航断链:Tab 走到一半跳回,或永远走不到某个控件。
|
|
75
|
+
- 焦点环缺失、错位、被裁剪,或焦点落在不可见元素上。
|
|
76
|
+
- 焦点陷阱:弹窗里 Tab 出不去,或 Tab 跑到弹窗背后。
|
|
77
|
+
- Tab 顺序与视觉顺序不一致。
|
|
78
|
+
- 表单用键盘提交时错误提示不可达、不被读出。
|
|
79
|
+
- 空格/Enter 在某控件上触发错误动作。
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## L3 · 鼠标 + 键盘 + 快捷键 / Full input
|
|
84
|
+
|
|
85
|
+
**允许 Allowed**:L1 + L2 全部,加上修饰键组合与功能键。
|
|
86
|
+
|
|
87
|
+
**仍然禁止 Still forbidden**:内部指针指令(R1 任何级别都不放开)、用脚本或宏代替人工操作。
|
|
88
|
+
|
|
89
|
+
**特有要求 / Extra requirement**
|
|
90
|
+
|
|
91
|
+
每条功能至少走两条路径,并比对结果一致性 / Every feature must be exercised through at least two
|
|
92
|
+
paths, and the results compared:
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
路径 A:菜单/工具栏/鼠标完成 → 结果 R_A
|
|
96
|
+
路径 B:快捷键完成 → 结果 R_B
|
|
97
|
+
判定:R_A 与 R_B 的界面结果、数据结果、状态是否一致
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**能抓到的缺陷 / Defects this level catches**
|
|
101
|
+
|
|
102
|
+
- 快捷键无效、被系统或其他应用抢占、与菜单显示的快捷键不一致。
|
|
103
|
+
- 快捷键在特定上下文(输入框聚焦、弹窗打开)误触发。
|
|
104
|
+
- 两条路径结果不一致(菜单路径保存成功,快捷键路径静默失败)。
|
|
105
|
+
- 快捷键在非英语键盘布局下失效。
|
|
106
|
+
- 快捷键提示在 UI 上写错(显示 ⌘S 实际是 ⌘⇧S)。
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 升降级规则 / Escalation rules
|
|
111
|
+
|
|
112
|
+
```text
|
|
113
|
+
默认:先跑完全部用例的 L1,再跑全部用例的 L2,再跑全部用例的 L3。
|
|
114
|
+
例外:某用例在 L1 发现缺陷 → 在 L2、L3 立即复现一次并登记"是否跨模式复现"。
|
|
115
|
+
降级:用户未授权键盘 → 只跑 L1,L2/L3 全部标"未覆盖(无键盘权限)"。
|
|
116
|
+
降级:设备不支持该模式(如 iPhone 无外接键盘)→ 标"不适用(设备限制)",不要臆测结果。
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
```text
|
|
120
|
+
Default: all cases at L1, then all at L2, then all at L3.
|
|
121
|
+
Exception: a case that fails at L1 is immediately re-run at L2 and L3 and tagged "reproduces across
|
|
122
|
+
modes?".
|
|
123
|
+
Degrade: no keyboard permission → L1 only, L2/L3 marked "not covered (no keyboard permission)".
|
|
124
|
+
Degrade: the device cannot support the mode (an iPhone with no external keyboard) → mark "not
|
|
125
|
+
applicable (device limitation)". Never guess the result.
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 禁止"聪明的替代" / No clever substitutes
|
|
129
|
+
|
|
130
|
+
- 不许用"我先用快捷键做完,再补一次鼠标点击"来伪造 L1 结果。
|
|
131
|
+
- 不许用"在开发者工具里点一下"代替真实点击。
|
|
132
|
+
- 不许把未执行的模式标成通过。
|
|
133
|
+
- 不许在测试中途改变操作模式来绕过卡住的步骤;卡住本身就是一条缺陷。
|
|
134
|
+
|
|
135
|
+
Do not fake L1 by shortcut-then-clicking afterwards; do not click through a developer console instead
|
|
136
|
+
of the real UI; never mark an unexecuted mode as passed; never change modes mid-case to get unstuck —
|
|
137
|
+
being stuck is itself the finding.
|