AI测试-03-Scenix项目实战复盘
第十四章前两篇如果只停留在“AI 测试值不值得做”和“Midscene.js 能解决什么问题”,很容易还是概念层内容。
真正能把这一章立住的,还是得回到一个具体仓库,拆它现在已经做到了什么、没做到什么、下一步该优先补什么。
这篇就只看一个项目:
Scenix。
这次复盘不是根据宣讲材料写,也不是根据一张架构图去反推,而是直接基于本地仓库 /tmp/scenix 的内容来判断,包括:
README.mddocs/design.mddocs/development-plan.mdclient / server / core / tests的工程结构
先说结论:
Scenix 现在已经跨过了“纯脚手架”阶段,最小可用链路基本成形,但还远不到成熟可用。
它和不少只停留在“AI 自动化愿景说明”的仓库不一样,已经能看到这些具体事实:
- 前后端分层是明确的
SQLite持久化已经落地- 测试套件执行链路已经串到
TestRunner SSE实时推送已经打通- Web、Android、iOS 三类 Agent 入口已经存在
但如果把标准提高到“团队可以长期依赖”的平台,Scenix 现在最明显的问题也已经暴露出来了:
- 执行链路可以跑,但还不够稳
- 报告结构已经有入口,但证据闭环不完整
- 设备发现已经有了,但资源调度和占用治理还不成熟
- 架构已经分层,但很多能力还停留在第一版
所以这篇文章不写产品介绍,而是只回答 6 个问题:
- 为什么要做这个项目
- 当前架构到底是什么
- 最小可用链路已经闭合到什么程度
- 现在最有价值的阶段成果是什么
- 还不成熟的部分具体卡在哪里
- 下一步最该优先补哪几块
一、为什么要做:不是为了把自然语言接到 UI 自动化上,而是为了把“自然语言测试”变成可管理的执行系统
从 README.md 和设计文档看,Scenix 的目标很明确:
- 基于
Midscene.js和Appium - 用自然语言描述测试步骤
- 覆盖
Web / Android / iOS - 以测试套件为执行入口
- 用“套件总报告 + 子用例报告”组织结果
这个方向本身不新鲜。
真正有价值的部分不在“自然语言写步骤”,而在于它没有把项目停留在单机脚本层,而是继续往平台化方向推进了:
- 有前端页面
- 有后端 API
- 有持久化
- 有实时状态推送
- 有测试套件模型
这说明项目真正想解决的问题不是“写一个 AI Agent 跑页面”,而是下面这件事:
把 AI 驱动的 UI 自动化能力,从单次脚本执行,收敛成一个可创建、可编排、可运行、可观察、可复看的系统。
这个判断很关键。
因为如果只是做 PoC,通常只需要:
- 写一个示例脚本
- 接一个模型
- 跑一次页面操作
- 输出一份报告
但 Scenix 明显不是停在这里。
它已经开始处理平台阶段才会遇到的问题:
- 用例和套件如何建模
- 执行状态如何实时同步
- 报告目录如何统一
- 数据如何跨重启保留
- 移动端设备如何进入执行入口
这也是 Scenix 当前最值得肯定的一点:
方向上并没有把 AI UI 自动化理解成“多写几个 Prompt”,而是已经开始往工程化收口。
二、当前架构:不是一个单体脚本仓库,而是比较清晰的三层结构
从工程结构看,Scenix 已经形成了比较标准的三层拆分:
client:前端控制台,React + Vite + Ant Designserver:控制面和数据面,Express + SQLite + SSEcore:真正执行测试的核心层,负责解析步骤并分发到不同 Agent
这套拆法是合理的,因为 AI 测试平台最怕的一件事,就是把所有逻辑都堆在执行脚本里。
一旦这样做,后面这些能力会非常难补:
- 用例管理
- 套件编排
- 状态同步
- 执行记录
- 结果归档
Scenix 当前的结构至少避免了这个问题。
1. 前端层负责控制台而不是执行逻辑
client/src/pages 下面已经能看到:
Dashboard.tsxTestCases.tsxTestSuites.tsxTestRun.tsxReports.tsxDevices.tsx
这说明控制台的页面模型已经基本拉出来了。
它不是只有一个演示页,而是把平台最核心的对象都分开了:
- 用例
- 套件
- 执行
- 报告
- 设备
同时,useSSE.ts 说明前端已经不是纯轮询刷新,而是开始按事件驱动更新执行状态,这对测试平台很重要。
因为测试执行类系统如果没有实时反馈,使用体验会退化得很快。
2. 服务端层开始承担平台控制面的职责
server/src/routes 里已经有:
test-cases.tstest-suites.tstest-runs.tsdevices.tsevents.ts
这里最值得注意的是 test-runs.ts。
它不是简单记录“用户触发了一次执行”,而是已经在做这些事:
- 校验
suiteId - 校验平台和设备是否匹配
- 创建
test_runs - 创建
test_run_items - 先返回
201 - 再异步执行
executeSuiteRun - 状态变化后广播
test-run:updated
这说明 Scenix 已经开始从“执行命令式接口”走向“有状态执行对象”的平台模式。
这一步很重要,因为一旦执行对象没有状态机,后面就很难做:
- 列表展示
- 实时进度
- 错误归因
- 结果回看
3. 核心执行层保持了平台无关性
core/src/runner/test-runner.ts 的职责比较清楚:
- 解析自然语言步骤
- 按平台分发到
web / android / ios - 按步骤调用
aiAction()或aiAssert() - 统一返回
TestResult
从架构角度看,这是当前仓库里最像“核心抽象”的一层。
它没有把前端和数据库逻辑卷进去,也没有把路由层耦死到具体平台执行代码里。
这层虽然还比较轻,但方向是对的。
三、最小可用链路:现在已经能闭合,但还只是第一版闭合
判断一个 AI 测试平台是不是已经跨过脚手架阶段,最直接的方式不是看页面多不多,而是看有没有一条真实可用链路。
Scenix 现在已经具备下面这条最小可用链路:
- 创建测试用例
- 把一个或多个同平台用例编进测试套件
- 从测试套件发起执行
- 根据平台选择是否要求设备
- 服务端持久化执行记录和子项记录
- 调
TestRunner真正执行 - 前端通过
SSE实时看到状态变化 - 执行结果写回列表和报告入口
这条链路为什么重要?
因为它说明项目已经不只是“能跑一个 AI 步骤演示”,而是已经把下面几种对象连起来了:
- 测试定义对象
- 套件对象
- 执行对象
- 设备对象
- 状态对象
最小可用链路的实际骨架
如果按工程视角去拆,Scenix 当前的最小链路大概是这样:
第一段:定义层
test_cases表持久化测试用例test_suites+test_suite_cases建立套件和用例关系
第二段:触发层
POST /api/test-runs- 根据
suiteId查套件 - 根据平台决定是否要求
deviceId
第三段:执行层
- 服务端把状态从
pending改成running executeSuiteRun()顺序执行同一套件里的各个用例TestRunner再按平台分发给Web / Android / iOS Agent
第四段:反馈层
event-bus.ts广播test-run:created与test-run:updated- 前端
useSSE订阅后刷新列表和详情
第五段:结果层
- 执行记录持久化进
test_runs和test_run_items - 报告目录统一挂到
/reports和/midscene_run
这已经是一条完整链路了。
但要注意,它现在还是:
第一版闭合,不是成熟闭合。
它能用来证明“这个平台方向是能跑起来的”,但还不足以证明“这个平台已经适合团队长期依赖”。
四、关键模块拆分:当前最有价值的不是功能多少,而是边界已经初步成形
从项目当前状态看,最值得保留的不是某个页面,而是这几个模块边界已经比较清楚。
1. 用例模块和套件模块分开了
Scenix 明确区分了:
- 单条自然语言测试用例
- 套件级执行入口
这比“直接执行单条 case”更适合平台化。
因为一旦执行入口直接绑到单 case,后面套件编排、顺序控制、汇总报告都会变得很别扭。
现在的建模至少做对了两件事:
- 用例是原子定义单元
- 套件是运行组织单元
同时 test-suites.ts 里还有一个重要校验:
- 同一套件里的用例必须属于同一平台
这说明项目已经开始在模型层控制边界,而不是等执行时再碰运气。
2. 执行记录和执行子项分开了
数据库层有:
test_runstest_run_items
这个设计很关键,因为套件执行天然就是“一个总记录 + 多个子执行项”的关系。
如果没有 test_run_items,后面会很难处理:
- 套件内单条 case 的状态差异
- 多条 case 的错误定位
- 总状态与子状态的映射
虽然这套模型现在还不算丰富,但方向没有问题。
3. 设备发现和执行设备选择分开了
server/src/services/device-service.ts 当前做的是“发现设备”,包括:
- Android 通过
adb devices -l - iOS 在
darwin下通过xcrun xctrace list devices或idevice_id -l
同时 iOS 设备还会结合 IOS_WDA_HOST 和 IOS_WDA_PORTS 生成带 wdaPort 的设备项。
这说明 Scenix 已经意识到移动端执行不是只拿一个 udid 就够,至少还得考虑:
- 平台差异
- WDA 连接配置
- 设备列表刷新
虽然还没有走到资源治理那一步,但设备对象已经进入平台模型了。
4. SSE 事件总线和页面订阅是成对出现的
有些平台类项目会只做后端广播,不做前端重连和页面消费;也有些会只做前端刷新,不做真正事件流。
Scenix 现在是两边都落了:
- 后端有
event-bus.ts - 前端有
useSSE.ts
而且设计文档里明确写了:
- 事件类型
- 心跳
- 指数退避重连
这意味着“执行是异步过程”这件事已经被认真对待,而不是只写了一个演示级接口。
五、阶段成果:哪些地方已经明显不是 PoC 水平
如果把标准定成“是否已经从演示项目进入第一版可用项目”,Scenix 当前至少有 5 个阶段成果是明确的。
1. 数据已经不再是内存态
docs/development-plan.md 把项目早期痛点写得很清楚:
- 早期版本是内存数组存储
- 服务重启会丢数据
- 执行只是模拟
而现在 server/src/db/index.ts 已经做了这些事:
- SQLite 初始化
- 自动建表
WAL模式- 索引创建
snake_case -> camelCase映射
这说明 Scenix 至少已经从“演示态”跨到了“可保留对象”的阶段。
2. 执行已经从模拟跑法切到了真实 Runner
开发计划里把“对接 TestRunner”单独列成 Phase 2,当前代码里也能看到 test-runs.ts 已经直接引用了:
TestRunnertype TestCaseInput
这比“点击执行后 sleep 3 秒再改状态”成熟很多。
因为它说明平台最关键的价值链路已经开始和真实执行对接,而不是继续留在假执行状态。
3. 状态同步已经不是手动刷新
执行系统如果只能手动刷新,基本还属于半成品。
Scenix 现在的 SSE 链路虽然不复杂,但足够说明项目已经认真处理“状态流”了。
这件事的价值不只是体验更好,而是它让这些对象开始具备真正的平台属性:
- 正在运行
- 已经失败
- 已经完成
- 被删除
这些变化不是页面上临时算出来的,而是有事件驱动。
4. 跨平台边界已经显式写进执行模型
README.md 明确写了:
- Web 套件不需要设备
- Android 套件需要 Android 设备
- iOS 套件需要 iOS 设备和 WDA 配置
而 test-runs.ts 里也有对应校验逻辑。
这说明 Scenix 没有试图把三端执行强行揉成一个“统一设备模型”,而是接受了多平台差异本来就存在。
这是对的。
AI 测试平台如果一开始就想把所有平台差异抹平,后面往往会在真实执行里出问题。
5. Monorepo 结构让后续扩展空间是存在的
pnpm workspace + client/server/core 这种结构虽然不新鲜,但对这类项目是合适的。
因为后面真要继续做:
- 模型配置治理
- 报告详情页
- 并行执行
- 定时执行
- 权限控制
都需要前端、服务端、执行层分别演进。
现在这三层至少已经拆出来了。
六、还不成熟的部分:当前最明显的缺口有 6 个
Scenix 最大的问题不是“有没有想法”,而是:
已经跨进了平台阶段,所以它的短板也开始从脚本问题变成平台问题。
1. 报告入口存在,但证据闭环还不完整
仓库里已经有:
Reports.tsx/reports静态目录reportPath
这说明项目知道报告是核心结果对象。
但从当前 TestRunner 返回值看,reportPath 并不是稳定落地的强约束,执行结果更多还是状态和错误信息级别。
这会带来一个直接问题:
- 能知道失败了
- 但不一定能完整复盘失败现场
AI UI 自动化项目最怕这种状态。
因为这类问题天然比传统脚本更需要证据链,至少要能稳定对应到:
- 原始步骤
- 模型动作
- 关键截图
- 执行日志
- 报告入口
当前仓库已经有报告目录概念,但还看不到足够成熟的证据分层。
2. 套件执行是顺序链路,但还不是成熟调度链路
executeSuiteRun() 现在是直接在服务进程里顺序跑。
这对第一版是可以接受的,因为实现简单,也容易把链路先跑通。
但它的边界也很明显:
- 没有真正的任务队列
- 没有并发治理
- 没有租约
- 没有执行隔离
- 没有 worker 层的状态回传协议
只要执行量稍微上去,下面这些问题就会出现:
- 一条长任务拖住整个服务进程
- 多设备、多套件时资源互相抢占
- 服务重启时运行中状态难以收敛
- 失败任务的补跑和恢复不好做
这说明 Scenix 现在更准确的状态是:
已经有执行模型,但还没有成熟调度模型。
3. 设备能发现,但设备资源还没有真正被治理
当前 device-service.ts 解决的是“发现什么设备在线”,但没有真正解决这些问题:
- 设备是否被哪个任务占用
- 设备是否处于脏状态
- 设备是否能安全复用
- 设备失败后该怎么恢复
- iOS 多端口映射是否会冲突
也就是说,现在的设备对象更像“可选项”,还不是“被治理的资源”。
对移动端 AI 自动化来说,这个缺口会很早暴露。
4. AI 配置已经集中,但执行质量治理还没有深入展开
开发计划里把 AI 配置模块 列得很清楚,也说明支持:
- OpenAI
- Qwen
- Anthropic
这说明模型配置集中管理已经开始做了。
但当前仓库里还看不到足够成熟的这些能力:
- 不同模型的行为差异治理
- Prompt/指令模板版本治理
- 失败重试和重规划的可观测性
- 幻觉动作与误断言的归因分层
当前 TestRunner 只是按步骤调用 aiAction() / aiAssert(),失败时统一报“最多已尝试 3 次重规划”。
这对于第一版能跑是够的,但对于平台排障远远不够。
5. 执行状态有了,但业务决策状态还没有形成
当前状态机主要是:
pendingrunningpassedfailederror
这对执行系统是够用的。
但如果平台继续往前走,后面一定会遇到更细的决策问题:
- 是否允许忽略
- 是否允许重跑
- 是否属于环境问题
- 是否属于脚本问题
- 是否属于模型误判
如果没有这层更细的决策模型,平台最终仍然会退化成“看一个总状态颜色”的系统。
6. 当前仓库更像单实例系统,还没有走到多用户长期使用阶段
SQLite、单服务进程、SSE、本地设备发现,这些组合在第一版是合理的。
但也意味着当前架构更适合:
- 小规模使用
- 本地或单机部署
- 快速验证方向
它还不适合直接外推成:
- 大规模多人共用
- 多实例执行
- 长期排队调度
- 多角色协作
这不是缺点,而是阶段事实。
但复盘时必须写清楚,不然很容易把“第一版可用”误写成“平台已经成熟”。
七、最该先补什么:优先顺序不是功能越多越好,而是把执行闭环补稳
如果现在继续往前做,最容易犯的错就是继续加页面、加概念、加模型支持。
但 Scenix 当前最缺的不是广度,而是稳定闭环。
更合适的优先顺序是下面这 5 件事。
1. 先补“执行证据包”
每次执行至少要稳定留下:
- 套件级元数据
- 子用例级步骤记录
- 关键截图或页面快照
- 模型动作和断言日志
- 错误归因字段
- 报告入口映射
没有这层证据包,后面排障会非常痛苦。
2. 再补“设备与执行资源治理”
移动端执行要尽快补的不是新页面,而是:
- 占用状态
- 租约
- 执行前探活
- 执行后回收
- 脏设备恢复
- 失败后隔离
否则平台一旦多人使用,最先崩的往往不是模型,而是设备环境。
3. 把“顺序执行”升级成“受控调度”
第二阶段不一定非要上复杂分布式系统,但至少要开始拆出:
- 调度入口
- 执行 worker
- 任务状态回传
- 超时和中断治理
只有这样,平台才能逐步支持:
- 排队
- 并行
- 补跑
- 自动恢复
4. 把 AI 失败分层写进结果模型
当前失败状态还比较粗。
后面至少要把这几类失败区分开:
- 环境失败
- 设备失败
- 模型理解失败
- 页面元素不可操作
- 断言失败
- 配置失败
只有把失败分层写进模型,报告和治理才会开始真正有价值。
5. 最后再考虑更大的平台能力
例如:
- 定时执行
- 标签和分组
- 权限
- PostgreSQL 迁移
- 覆盖率
这些都可以做,但不该排在最前面。
因为在 Scenix 当前阶段,真正的瓶颈不是“功能不够多”,而是“执行和证据还不够稳”。
八、常见坑:这类 AI 测试平台最容易在 4 个地方看起来能用,实际不好用
1. 能执行,不等于可复盘
只要测试开始真的跑起来,就很容易把平台判断成已经成形。
但如果失败后不能快速回答下面这些问题,平台还是会卡住:
- 哪一步失败了
- 当时页面是什么状态
- 是模型理解错了,还是页面没准备好
- 是设备问题,还是环境问题
2. 有设备列表,不等于设备资源可用
设备能发现出来,只说明“看见了”。
它不说明:
- 当前设备是否空闲
- 当前端口是否可用
- 当前 WDA 是否可通
- 当前系统状态是否干净
3. 有实时状态,不等于执行链路稳定
SSE 做好之后,平台会显得“更像平台”。
但这解决的是观察问题,不是执行稳定性问题。
如果没有调度、重试、回收、证据包,实时状态只能让问题看起来更明显,不能让问题更容易解决。
4. 有三端 Agent,不等于跨平台能力已经成熟
Web、Android、iOS 的 Agent 入口都有了,这是好事。
但真正困难的是:
- 三端失败模式不一样
- 三端环境准备不一样
- 三端证据采集不一样
- 三端恢复动作也不一样
这部分如果没有继续往平台能力里收,三端支持很容易停留在“入口存在”。
九、真实案例型段落:一条套件已经发起,但页面上长时间停在运行中,最后并不是模型没返回
场景
一条 Android 测试套件已经在控制台创建完成,设备列表里也能看到目标真机。
点击执行后,前端 TestRun 页面出现了新记录,状态从 pending 变成了 running,但长时间没有进入最终状态。
执行
先从最短路径检查:
- 前端是否收到
test-run:created - 前端是否收到后续
test-run:updated test_runs和test_run_items是否已经写入- 服务端是否真的进入了
executeSuiteRun() - 设备选择是否和套件平台一致
现象
检查下来会发现:
- 执行记录已经插入数据库
test-run:created已经广播- 总状态已改成
running - 但子项迟迟没有稳定推进到
passed / failed / error
这时候很容易先怀疑模型调用慢,或者 Midscene 卡住。
排查
如果只盯模型层,很容易走偏。
更有效的顺序应该是:
- 先确认是不是 Web / Android / iOS 平台选择错误
- 再确认
device-service.ts返回的设备对象是否真能用于执行 - 再看
TestRunner是否已经拿到正确的deviceUdid / deviceConfig - 最后才回到 Agent 执行和模型响应
在这类链路里,最容易漏掉的是:
- 设备列表能显示,不等于设备当前真可执行
- iOS 的
wdaHost / wdaPort组合能生成,不等于链路真打通 - 总状态进入
running,不等于子项执行已经稳定开始
修复
更稳的修复方式不是只补一个超时,而是补三件事:
- 执行前加入设备探活和可执行校验
- 子项开始执行前记录更明确的阶段日志
- 把“设备可见但不可执行”单独归类成设备层错误,而不是混进模型失败
这类问题很典型。
从页面看像“AI 执行慢”,从执行链路看其实更像“平台还缺少设备层的前置校验和错误分层”。
十、这篇复盘的最终判断
Scenix 当前最准确的阶段判断不是:
- 一个成熟可用的 AI 测试平台
也不是:
- 一个只会画架构图的概念仓库
而是:
一个已经把最小可用链路跑通、并且明显开始进入平台工程阶段的第一版项目。
它现在已经有几件事是明确成立的:
- 有对象模型
- 有前后端分层
- 有真实执行入口
- 有持久化
- 有实时状态推送
- 有跨平台执行边界
但同样也要明确写清楚:
- 报告证据闭环还不成熟
- 调度和资源治理还不成熟
- 设备治理还不成熟
- AI 执行失败分层还不成熟
- 长期多人协作使用能力还不成熟
如果下一步继续推进,最值得先做的不是继续扩功能面,而是把下面这条链路补稳:
套件定义 -> 设备校验 -> 受控执行 -> 结构化证据 -> 失败分层 -> 可复盘报告
只要这条链路补稳,Scenix 才会从“已经能跑起来的 AI 测试平台第一版”,真正往“可长期使用的测试平台”继续走。