9.2 Midscene 的 E2E 桥:自然语言进测试体系


9.2 Midscene 的 E2E 桥:自然语言进测试体系

本节摘要:本节处理固化光谱的中间地带:值得纳入测试体系、又不值得(或不适合)写死成纯代码的任务——断言「页面主体可见」「搜索结果与关键词相关」这类感知性内容。工具是第 5.2 节的 Midscene(约 1.5 万 stars,MIT,中文文档第一梯队):三件套以测试用例的形态进入体系,ai 写操作、aiQuery 抽数据、aiAssert 做感知断言,JS 侧嵌进 Playwright 测试(也可独立脚本),Python 侧对应 pytest 形态(以官方中文文档为准)。AI 断言进 CI 的两条纪律先立住:误判走复核流(感知断言的失败先出报告人工复核,不直接熔断——第 6.1 节口径的 CI 版),报告归档(每次运行的视觉证据进第 8.3 节事件流)。然后是三层混合策略:纯代码冒烟打底(快、稳、零成本)、Midscene 语义用例补盲(感知与语义断言)、关键流程两者并用(结构断言加 aiAssert 双保险)。flake 对比给一张示意表(标注示意值,以各自环境实测为准):自然语言用例的表达力换来略高的不稳定性,靠分层运行节奏把差异控制在可接受面。收在轨迹回放:Midscene 报告作为回归资产的一部分。

学习目标

  • 写出嵌进测试体系的 Midscene 用例(JS 与 Python 双语形态)。
  • 复述 AI 断言进 CI 的两条纪律(复核流、报告归档)。
  • 设计三层混合策略并说明每层的运行节奏。
  • 解读 flake 对比表(示意值)并说出控制手段。
  • 把 Midscene 报告接进审计事件流与回归资产。

一、中间地带:感知性内容进不了纯代码

第 9.1 节把「值得死板」的任务搬进了纯代码,剩下的任务里有一类处境尴尬:它们属于测试体系(要随每次回归跑),但抗不出纯代码断言——「页面主体内容可见、无报错遮罩」「搜索结果与关键词相关」「上传后的图片预览没有变形」。第 5.2 节的结论在这里直接适用:结构性断言用代码,感知性断言用自然语言,关键流程并用。Midscene 的价值就是把后半句接进测试体系——自然语言写用例,模型执行与判定,测试框架负责运行与报告。

它与第 9.1 节固化管道的关系是补充而非替代:固化管道处理「路径确定」的流程(Playwright 代码),Midscene 桥处理「断言感知」的验证(aiAssert),两者在同一条 CI 流水线上各司其职。

二、用例形态:双语进测试体系

JS 侧嵌进 Playwright 测试(Jest 形态同理,以官方文档为准):

// todo.spec.mjs —— Midscene 语义用例嵌进测试体系(写法示意,以官方文档为准) import { expect, test } from "@playwright/test"; import { PlaywrightAgent } from "@midscene/web/playwright"; test("自然语言添加待办,感知断言与代码断言并用", async ({ page }) => { await page.goto("http://127.0.0.1:8080/demo_todo.html"); const agent = new PlaywrightAgent(page); await agent.ai("在「新待办」输入框填入 买牛奶,点击「添加」按钮"); await agent.aiAssert("列表中包含一条内容为 买牛奶 的待办"); // 感知断言 await expect(page.getByRole("listitem")).toContainText("买牛奶"); // 代码兜底 }); ​

Python 侧的 pytest 形态(包名与断言入口以官方中文文档为准):

# test_todo_ai.py —— Midscene 的 Python 用例形态(写法示意,以官方中文文档为准) from midscene import Agent def test_add_todo() -> None: agent = Agent.from_playwright("http://127.0.0.1:8080/demo_todo.html") agent.ai("在「新待办」输入框填入 回复邮件,点击「添加」按钮") agent.ai_query("提取待办列表的全部条目文本") agent.ai_assert("列表中包含一条内容为 回复邮件 的待办") agent.release() ​

两侧的分工沿用第 5.2 节的两步走:先在报告与回放工具链成熟的 JS 侧把用例调通(排障快),再按工程栈归属决定落地侧——测试基建在 Node 系就留 JS,团队主栈是 Python 就翻译过去。指令文本与断言语义两侧原样复用(它们本来就是自然语言),翻译成本为零。唯一要双侧各留一份的是夹具层(视口、前置数据、报告路径),这部分进公共配置而不是复制粘贴。

写用例的三条纪律从第 5.2 节原样继承:固定视口(用例默认头部)、断语写可观察事实(「列表包含买牛奶」而非「页面正常」)、指令写用户视角。补充一条 CI 特有的:用例自足——每条用例自己准备数据、自己清理(或接受幂等),CI 的执行顺序不能成为隐含前提。断语改写的对照示例:

模糊断语(易抖动) 改写后(可观察,推荐)
页面看起来正常 主体内容可见且无报错遮罩
加载完成了 列表区域渲染出至少一条条目
排版没乱 输入框与「添加」按钮均在视口内可见

改写的共同套路:把主观形容换成可数、可见、可判定的陈述——模型判读这类断语的抖动面远小于主观形容,这也是第五节抖动表里「断语边界模糊」一条的主要治理手段。

三、AI 断言进 CI:两条纪律

感知断言的误判概率(第 5.2 节承认的那个代价)在 CI 语境下被放大:CI 的失败信号直接驱动人的注意力,误报多了就是狼来了。两条纪律兜住:

纪律 做法 违反的后果
误判走复核流 aiAssert 失败先标记「待复核」并出报告,人工确认后才升级为真实缺陷 误报骚扰与信任流失
报告归档 每次运行的可视化报告(截图、判定依据)作为证据指针进第 8.3 节事件流 复核无据可查,争论没有裁判

复核流的工程形态很轻:测试框架的 retry 与软失败标记(soft assertion)都够用,关键是分级——感知断言的失败在告警系统里属于「黄」不是「红」(第 11.2 节告警分级的前置呼应)。纯代码断言维持「红」的待遇:它几乎不误判,失败就该拉响。判定冲突时的仲裁规则也要先写好:代码断言与 aiAssert 一个过一个不过时,以代码断言为准(它判定的是结构事实),aiAssert 的分歧进复核——这条规则免去了每次失败现场争论「听谁的」。

报告归档的形态:报告目录按运行组织(runs 加运行标识),事件流的 evidence 字段存目录路径而非单文件——回放时整个目录一起取,截图、推理、判定依据一次到齐。

四、三层混合策略

层 工具 覆盖 运行节奏(示意) 成本
冒烟层 纯 Playwright 核心路径结构验证 每次提交 零 token
语义层 Midscene 用例 感知与语义断言 每日定时 每用例若干次模型调用
关键层 两者并用 支付、权限、发布敏感项 发布前 双份成本买双保险

分层的原则是按失败信号的可靠性排节奏:越可靠的信号跑得越频繁、越靠近开发反馈环;带误判面的信号往后放、频率降低,用复核流消化不确定性。这也是成本的自然分配——模型调用集中在低频高价值的语义层与关键层,高频冒烟保持零成本。层的归属不是永久的:一条语义用例连续一个月零误判,可以提名降层提速;一条冒烟用例开始频繁因改版挂掉,说明它断言的其实是语义(比如「主入口可达」),该升层交给 aiAssert——月度回顾时按第 11.1 节稳定率数据调层,是这套策略保持鲜活的机制。

五、报告与轨迹回放:回归资产的另一半

第 5.2 节说过 Midscene 每次操作产出可回放的中间材料(带定位框截图、推理与动作输出、断言判定依据)。进了测试体系之后,这些报告的定位要升级:它们是回归资产的证据层,与测试代码同等重要地被版本管理与检索。

动作 做法 产出
归档 每次运行的报告路径作为 evidence 指针写入第 8.3 节事件流 可按 run_id 检索的证据库
回放 失败用例的三步复盘:看报告截图、对照当时快照、查事件时间线 一份「当时发生了什么」的叙事
沉淀 月度回顾高频失败的断语,改写清单进用例模板 断语口径的持续收敛

回放的价值在「失败的历史可解释」:一条语义用例这个月挂了三次,回放三次的报告往往能看出模式(都是懒加载区域、都是视口底部元素)——这类模式正是第 11.1 节 flake 归因的输入。沉淀的价值在「断语口径越用越准」:模糊断语(「页面正常」)在月度回顾里被逐步替换成可观察断语(「主体内容可见且无报错遮罩」),用例集随时间自我改良。

与第 9.1 节回归任务集的关系:任务集是骨架(哪些用例、什么节奏跑),报告库是血肉(每次跑的证据)。只有骨架没有血肉的测试体系,失败时只能靠现场重跑取证——那是最慢的排障路径。

六、flake 对比与控制(示意值)

指标(示意值,以各自环境实测为准) 纯 Playwright Midscene 用例
千次运行抖动率 低于百分之一 百分之一到百分之五
主要抖动源 时序与数据(第 11.1 节) 视口渲染差异、断语边界模糊
平均用例耗时 秒级 数十秒级
每次运行边际成本 零 模型调用费用

数字务必当作占位符读:真实数值随页面、模型、网络环境差异极大,这张表的用途是结构对比而非基准——Midscene 用例的抖动源多一类(语义判定的边界),因此控制手段也多一条:断语边界模糊的用例要么改写得更可观察(第 5.2 节坑表),要么降级到更低频层。抖动率的度量与治理统一归第 11.1 节,本章只需带着「示意值、须实测」的清醒。

补充一个常被忽略的联动:三层策略的成本与抖动会互相传导——语义层跑得越频繁,模型调用费用与抖动暴露面越大;把语义层降到每日之后省下的钱,一部分应该回投给第五节的报告归档(证据库越全,月度回顾改良断语的效率越高)。这是一个「频率换质量」的再平衡,团队按自己的告警噪音与预算找平衡点。

七、常见坑

坑 现象 排查与处理
感知断言当红色告警 CI 天天狼来了 复核流分级,黄色待复核
报告不留档 复核时靠回忆 报告路径进事件流 evidence 字段
语义层塞进提交钩子 提交变慢、费钱 语义层走每日定时,冒烟层守提交
断语模糊不修 同用例时过时不过 改写成可观察事实,或降层降频
密钥写进 CI 配置明文 流水线日志泄露 环境变量或密管注入(第 7.1 节)
报告只存最近一次 月度回顾无料可看 报告按运行归档进证据库(第五节)
用例互相依赖顺序 单跑即失败 用例自足纪律(第二节),CI 顺序无关化

本节要点回顾

  • 中间地带的定位:感知性内容属于测试体系但进不了纯代码,Midscene 桥把它接进来——补充固化管道而非替代。
  • 双语用例形态:JS 嵌 Playwright 测试、Python 走 pytest;纪律四条——固定视口、可观察断语、用户视角、用例自足。
  • AI 断言两条 CI 纪律:误判走复核流(黄不拉红)、报告归档进事件流。
  • 三层混合:冒烟(纯代码、每提交)、语义(Midscene、每日)、关键(并用、发布前)——按信号可靠性排节奏。
  • flake 对比表是结构不是基准:示意值须实测,抖动治理归第 11.1 节。

测试资产就位后,镜头拉回运行时:当任务量大到单个浏览器实例吃不下、账单开始引人注目,就进入了多智能体的领地。下一章讲并发与队列、实例池与速率协调,以及 token 成本的结构与省钱三招。

作者与出处
原作者:灏天文库
整理人: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U