🌐 中文 · English
「你永远没法第一次使用自己的 App。Agent 可以。」
把 App 交给几个互不通气的 Agent。让它们像第一次来的用户一样摸索,再把真正复现的问题整理成一份你能直接动手处理的产品改进清单。
做过一个 App 以后,你就失去了“第一次使用它”的能力。
你知道入口在哪,知道哪个加载值得等,也知道返回以后本来应该发生什么。再认真地点一遍,证明的仍然只是“作者会用自己的产品”。自动化测试也一样擅长守住已经写下来的预期,却不会主动告诉你:这里为什么让人误会,那一步为什么没人敢点,或者某个返回动作其实在背后悄悄创建了东西。
我想要的是一位随叫随到、完全不知道答案的陌生用户。它真的去找入口、点击、试错、返回、重试;然后再有人把关键状态走全,把每次动作前后的对象和数据对上。最后回来的不是一句“这里有点怪”,而是一份带着复现证据的改进清单。
第一次把这套方法用在一个真正的 Flutter App 上,它找到了几种很典型的问题:重启后列表从 4 条变回 0 条;只进新建页再返回,首页会多出空对象;提交失败后详情里还看得到内容,列表却像什么都没发生。它们都不是“某个像素不对”,而是产品世界在用户背后变错了。试点证据放在这里。
@blind-experience-test,去测这个 App。
Agent 先自己看项目、启动方式、产品说明和已有测试。能从仓库里确认的,就不再问你。
如果信息已经够了,它应该直接开始:
我看过项目了。先测新用户从创建到拿到第一个结果这条路,
使用隔离数据,不改代码。如果碰到原生权限或生命周期问题,
我再转到 Simulator。开始了。
如果真的缺东西,它只问缺的那一件:
还差一个不会碰到生产数据的测试账号或 reset 方式。
给我这个就行。
不是五道固定问卷,也不用先学会 A/B/C、subject lock 或 oracle。简单说,就是:能自己查到的别来烦你。
一轮先挑一条最重要的旅程,不搞全产品、全平台大会战。
- 让一位陌生用户真的去用。 它只知道产品是给谁的、要完成什么,不看源码、Git 历史和已知 Bug。它可以走错路,也可以放弃——这些本来就是结果的一部分。
- 沿语义锚点把关键状态走一遍。 Test ID、Semantics 和 ARIA 用来确保重要入口、主要动作,以及空、加载、成功、失败和恢复状态没有漏掉。
- 检查动作以后,世界到底变成了什么样。 新建、提交、返回、失败、重试和重启前后,对象有几个、身份是不是同一个、内容有没有留下,都要对得上。
主 Agent 负责把版本冻住、选测试表面、给不同任务分开上下文,最后从干净状态复现问题。其他 Agent 可以很便宜;关键是它们互相不知道答案,也不共享会变化的账号或设备状态。
这三件事是任务,不是组织架构。有三个隔离环境时可以并行,只有一台 Simulator 时就老老实实串行。
它叫产品改进清单。
不叫“需求清单”,是因为测试可以证明用户遇到了什么、问题能不能复现,却不能替你批准需求。每一项只是一个有证据、可以马上做决定的候选改进。
下面这些都来自那次 Flutter 试点:
| 发现 | 我们看到了什么 | 接下来怎么改 |
|---|---|---|
| 发布前必须修:数据连续性 | 建立几条内容后杀进程再打开,列表从 4 条变回 0 条 | 让对象跨进程恢复;回归测试覆盖“创建 → 冷启动 → 数量和身份不变” |
| 核心问题:幽灵对象 | 只进入新建页再返回,重复三次,首页多出三条空对象 | 首次有效输入后再创建,或退出空草稿时回收 |
| 核心问题:恢复断点 | 提交失败后详情里能看到内容,回到列表却找不到它,也不知道从哪重试 | 保留失败对象的身份,在详情和列表提供同一条重试路径 |
| 核心问题:可访问性 | 读屏和语义树无法分辨主要提交按钮是做什么的 | 给主要动作稳定、唯一的语义标签 |
| 体验可以更好:本地化 | 中文界面出现英文空状态,第一次进入时很像半成品 | 让空状态文案跟随当前语言 |
真正交付时,数据丢失、核心任务失败、安全隐私和无法恢复的问题会放在最前面;能完成但别扭的,放进体验优化;如果两种产品设计都说得通,Agent 会把证据摆出来,请你决定,而不是替你发明产品真相。
截图、运行记录和对象台账都留在附件里。你先读这一张清单就够了。
因为 Agent 在浏览器里最快,也最便宜。但前提是:浏览器里跑的真的是同一个产品。
如果 Flutter App 本来就有 production Web 版本,而且创建、身份、存储和生命周期没有被换掉,就先在那里把共享主流程测清。遇到权限、原生插件、secure storage、后台前台或进程重启,再把那一小段搬到 Simulator 或 Emulator。相机、麦克风、推送和安装升级之类,最后才上真机。
“能编译成 Web”不等于“可以在 Web 上证明原生行为”。快是手段,保真才是底线。
不会。
第一轮只测试,交回产品改进清单,然后停下来问你。你同意以后,Agent 才在隔离的后继版本里修一个根因簇、补需要的回归测试,再请一个没参与修改的 Agent 重新走那条路。
修复授权也不等于 merge、发布或部署授权。这些仍然分开。
把这个目录复制进项目:
# Codex
cp -R blind-experience-test .codex/skills/
# Claude Code
cp -R blind-experience-test .claude/skills/然后说:
@blind-experience-test,去测这个 App。
安装后,主 Agent 会先自己检查项目,只追问真正缺少的信息,然后用三类隔离任务测一条核心旅程。只有你明确要比较测试方法时,它才会切到 A/B/C benchmark。
Widget test、integration test、XCTest、Maestro 和 Playwright 负责守住已经知道的行为;Blind Experience Test 负责找到你还不知道要写什么断言。
一句话:盲测负责发现,确定性测试负责别让它再回来。
Superpowers 关心的是开发 Agent 有没有按正确的方法工作。它的 TDD 从一个已经知道的行为开始:先写一个会失败的测试,再写最小实现;它对 Skill 的测试也类似,先看没有 Skill 时 Agent 会怎样失败,再用压力场景验证 Agent 能不能守住规则。
Blind Experience Test 测的不是开发 Agent,而是正在运行的产品。测试者不知道源码、已知 Bug、标准答案和其他测试者的发现。它要找的是用户第一次进来会怎样理解、怎样走错,以及一次点击以后,屏幕背后的对象和状态到底发生了什么。
所以最短的区别是:Superpowers 让开发 Agent 证明自己把已知的东西做对;Blind Experience Test 让陌生 Agent 找到你还不知道哪里做错了。
它们正好可以接力:Blind Experience Test 发现未知问题,人决定正确的产品行为,Superpowers / TDD 把它变成一个会失败的回归测试并完成修复,最后再由一个新的盲测 Agent 验证真实体验。
- 陌生用户 Agent 不看源码、已知 Bug、标准答案和其他 Agent 的发现。
- 测试使用隔离账号、存储和设备,不碰生产数据;会变的环境不能在多个任务之间混用。
- 跑错构建、服务不可用或测试表面不保真,算测试环境问题,不硬说成产品 Bug。
- 删除真实数据、接受条款、输入私人凭据、合并、发布和部署,都需要另外授权。
blind-experience-test/
├── SKILL.md # Agent 的入口
├── references/ # 执行协议、状态 oracle 和结果格式
├── scripts/validate_runs.py
├── examples/ # 合成样例与匿名真实试点
├── agents/openai.yaml
└── README.md / README.en.md
现有运行文件可以这样检查:
python3 scripts/validate_runs.py --max-actions 40 \
--expected-sha 0123456789abcdef0123456789abcdef01234567 \
examples/state-audit-synthetic.json examples/arm-c-synthetic.json