AI UI 自動化測試定位器與斷言為何不穩?文章提出三層測試邊界
AI 断言不稳定、AI 定位器乱飘:这不是模型不行,是你没给它“测试边界”
文章指出,AI 撰寫 UI 自動化測試時定位器與斷言不穩,根源在於缺少明確測試邊界,並提出感知、斷言、執行三層規則。感知層要求先取得頁面快照並按優先級使用語義定位器,斷言層結合頁面、網絡和業務校驗,自愈只可修改定位器及等待條件,修改斷言須人工審批。退款頁面案例中,加入邊界後只有一條用例因文案微調而需更新,網絡層亦攔截了接口返回 500、但 Toast 顯示成功的假通過。
2026-10-25 11
版权
版权声明:
本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《 阿里云开发者社区用户服务协议》和 《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写 侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
简介: 本文揭示AI写UI自动化脚本不稳定的根源:非模型能力不足,而是缺乏明确的测试边界。提出三层围栏——感知(必先快照、禁用CSS/XPath)、断言(分工具/页面/业务三层,禁止单靠Toast)、执行(自愈仅限定位器,断言须人工审批),并提供可直接复用的边界模板。边界不是限制AI,而是让其从“猜测试”变为“可验证的协作者”。
上周,团队里一个测试同学跑来找我,表情有点崩。
“哥,我用AI写UI自动化,定位器今天能用明天就飘,断言时过时不过。我换了两个模型,还是这样。是不是现在的模型根本干不了这活?”
我让他把脚本打开。定位器写的是 page.click('.btn-primary.submit'),断言写的是 expect(page.get_by_text('提交成功')).to_be_visible()。
我问他:“你生成脚本之前,给AI看过页面结构吗?告诉过它定位器优先级吗?告诉过它‘提交成功’这个Toast不能作为唯一断言吗?”
他愣了一下:“没有。我就说‘帮我写一个提交订单的自动化脚本’。”
我说:“那你不是在用AI做测试,你是在让AI猜测试。 它猜对了,你觉得模型真强;它猜错了,你觉得模型不行。真正的问题在中间——你没给它测试边界。”
一、AI为什么“乱飘”?因为它在开放空间里做合理猜测
大模型有一个特点:信息不完整的时候,它会用“最合理的猜测”把空白填上。
你给它一句“帮我写提交订单的脚本”,它不知道你的页面长什么样,不知道按钮的class是稳定的还是哈希的,不知道提交后是跳转、弹Toast还是原地刷新。它只能按训练数据里最常见的写法给你生成一段——button.btn-primary、waitForTimeout(3000)、expect(text).toBeVisible()。
这段代码在它的“经验”里是合理的。但在你的系统里,class是构建时生成的、Toast是前端乐观更新的、接口可能返回500但页面照样弹成功。
AI的“乱飘”,本质是它在替你补全你没告诉它的假设。
断言不稳定也是同一个逻辑。语义断言(用自然语言让模型判断“页面是否正确显示了订单金额”)本身带有概率性,同一个页面,这次判过、下次可能判挂。模型不是“不稳定”,是你在用一个概率判断去替代确定性校验,却没有给它兜底规则。
所以问题不是“模型行不行”,是你有没有把“什么算对、什么能用、什么不能碰”画成边界,交给它。
二、测试边界到底是什么?三层围栏
我把给AI的测试边界拆成三层:感知边界、断言边界、执行边界。
第一层:感知边界——先“看”,再“动”
AI定位器乱飘,十有八九是因为它在“猜页面”。
Playwright MCP 的默认方案不是截图,是可访问性快照(ARIA snapshot):把页面转成结构化文本,包含元素角色、可访问名称、状态,以及一个 ref 标识。Agent看到的不是像素,是“这是一个textbox,名字叫用户名,ref是e5”。
边界的第一条规则:不允许AI在没拿到快照的情况下写任何操作。
执行流程
步骤1:侦察页面(必须执行,不可跳过)
先调用 browser_snapshot 获取当前页面快照。
步骤2:基于快照中的 ref 执行操作
禁止凭经验猜测 CSS 选择器或 XPath。
步骤3:导航或DOM更新后,重新获取快照
ref 只在当前快照内有效,过期 ref 会导致点错元素。
第二条规则:定位器优先级写死。
定位器优先级
- getByRole — 首选,基于可访问性树
- getByLabel — 表单字段
- getByText — 文本是业务语义时使用
- getByTestId — 需要前端配合加 data-testid
- ❌ 禁用 XPath — DOM结构一变就断
- ❌ 禁用随机/哈希 class — 每次构建都可能变
把这两条写进 Skill 或系统提示词,AI就不会再用 .btn-primary 去猜按钮了。它不是不会用 getByRole,是没人告诉它“在这个项目里必须用”。
第二层:断言边界——三层校验,语义断言只做辅助
AI断言不稳定的根因,是把“判断”和“校验”混在了一起。
语义断言适合判断“页面语义上对不对”——金额是不是NaN、提示语是不是符合业务语气。但它不适合做唯一的成功标准,因为它有概率性,而且可能被“看起来合理但实际错误”的内容骗过去。
断言的边界要分三层:
工具层:动作没有抛异常,MCP工具没有返回 isError。
页面层:关键元素可见、关键文案出现。expect(locator).toBeVisible() 属于这一层。
业务层:捕获关键网络请求,校验状态码和核心字段;涉及订单、支付、库存的场景,通过接口或数据库确认最终状态。
规则要写死:不允许只用Toast、弹窗或按钮状态作为成功断言。 语义断言可以做第四层“语义合理性”的辅助判断,但不能替代前三层。
断言规范
- 禁止只断言 HTTP 200 或 Toast 可见
- 必须捕获关键请求,校验状态码和响应体核心字段
- 创建类操作必须通过业务查询接口确认最终状态
- 语义断言仅用于“文案合理性/视觉合理性”辅助判断,不作为唯一通过标准
第三层:执行边界——自愈可以修定位器,不能改断言
AI自愈是好事,但它有一个崩溃不具备的失败模式:它可以把一个真实的回归,修成一个通过的测试。
如果定位器“修”到了一个语义相近但不对的元素上,或者断言被“修”宽了,测试会绿,Bug会被藏起来。
执行边界要划清楚:
自愈只允许修 定位器 和 等待条件。
断言的修改必须走人工审批,不能自动合入。
每一次自愈记录完整日志:改了什么、为什么改、改前改后的定位器是什么。
自愈产生的修复以 PR/patch 形式提交,人工review后再合入。
三、一个真实的对比:加了边界之后,发生了什么
我们拿一个“退款申请”页面做了对比。
没有边界时,AI生成的脚本:
定位器用 .refund-btn 和 //div[@class="toast"]
断言只有 expect(page.get_by_text('提交成功')).to_be_visible()
第一次跑就报错,改了定位器能跑通;第二周前端改版,三条用例全红
更麻烦的是,有一次接口实际返回了500,页面照样弹了Toast,脚本判了通过
加了边界之后,同一个页面:
定位器全部改成 getByRole("button", {name: "申请退款"}) 和 getByRole("alert")
断言分三层:页面层校验退款单号出现,网络层用 expect_response 捕获退款接口并校验 code 和 refund_id,业务层调用查询接口确认订单状态变为“退款中”
前端改版后,只有一条用例因为文案微调需要更新,定位器一条没改
那个“接口500但Toast弹成功”的假通过,被网络层断言拦住了
模型没换,提示词没换,换的是“边界”。
四、可直接套用的边界模板
如果你现在就在用AI写UI自动化,把下面这段放进系统提示词或 Skill 里:
测试边界(必须遵守)
感知
- 写任何操作前,先获取页面快照
- 只使用快照中实际存在的 ref 或语义定位器
- 导航或DOM更新后重新获取快照
定位
- 优先级:getByRole > getByLabel > getByText > getByTestId
- 禁用 XPath 和随机/哈希 class
- 需要绝对稳定时,建议前端加 data-testid
断言
- 禁止只断言状态码或Toast可见
- 必须包含:页面关键元素 + 网络请求状态码/核心字段 + 业务最终状态(涉及资金/状态流转时)
- 语义断言仅作辅助,不作唯一通过标准
自愈
- 只修定位器和等待条件
- 不改断言
- 修复以 patch 形式提交,人工审批后合入
- 记录完整修复日志
五、避坑指南
坑一:只给自然语言,不给页面快照。 AI不是在“看页面”,是在“猜页面”。先快照,再生成。
坑二:让AI自由选择定位器。 不写优先级,它一定会用class或XPath——因为训练数据里最常见。
坑三:把语义断言当唯一标准。 模型会漂移,同一句断言今天过明天挂。关键数值和状态必须用确定性断言兜底。
坑四:让自愈自动合入。 自愈修错一个定位器,可能把一个真Bug修成绿色。修复必须走人工审批。
坑五:以为“边界”会限制AI的能力。 恰恰相反。边界不是给AI上锁,是把它从“猜”里解放出来。你告诉它“用getByRole、先快照、断言分三层”,它就不用把算力花在猜class名上,可以专注在流程编排和异常处理上。
最后
AI断言不稳定、定位器乱飘,不是模型不行,是你在让它做一个没有边界的开放题。
模型擅长的是“在给定规则下生成”,不擅长的是“猜你的项目里什么规则成立”。定位器优先级、断言分层、快照先行、自愈不改断言——这些是你的项目知识,不是模型的通用能力。你不给,它就只能猜。
测试边界不是限制AI,是让AI的产出可验证、可审计、可回归。 边界画清楚了,AI才从“一个会写代码的聊天机器人”,变成“一个能进流水线的测试协作者”。
下次它再乱飘的时候,别急着换模型。先问一句:我告诉它,什么能用、什么算对、什么不能碰了吗?
來源:阿里雲開發者社區 AI · developer.aliyun.com