☰
人工录制+AI补全:UI自动化脚本的省Token实战
2026/10/19 5:34:28 网站建设 项目流程

如果你试过让大模型从零生成一整段 UI 自动化脚本,大概率见过这种场面:代码写得像模像样,按钮选择器却是不存在的;断言写在点击之前;明明需要用户登录,脚本却假设页面已经登录好了。不是模型不够聪明,而是 UI 自动化本身对上下文极其敏感。后来我把思路换了一下:先用 Playwright codegen 人工把操作路径录制下来,再用 AI 按固定 Skills 补全脚本缺口。实测下来,同样一个回归用例的 Token 消耗能压到原来的三分之一左右,出错率低得多。这篇文章就把这套玩法从头到尾拆开讲,包括为什么要这样分工、具体怎么录制怎么补全,以及我在实际项目中踩过的坑。

1. 思路拆解:为什么是“人工录制 + AI 补全”,而不是全 AI 生成

1.1 全 AI 生成脚本的隐性成本

你可能会觉得,模型这么厉害,直接把需求描述扔进去,它不就能写出整套测试吗?实际上,那一整套往往是最贵的。UI 自动化脚本不是独立的小函数,它必须跟真实页面咬合,页面 URL、用户角色、DOM 结构、异步加载时机、接口返回结果,每一个变量都会影响脚本能不能跑。模型没有打开过页面,它只能靠训练数据里见过的类似网站脑补,于是你看到的是:选择器写了个#app,按钮路径靠猜,断言和点击顺序颠倒。

这份猜测的代价体现在三个地方。首先是 Token 消耗。一个“从零生成登录用例”的请求,往往要带上页面描述、业务说明、示例代码,一次调用几千 Token 很常见。生成出来的代码通常只有一半能用,剩下的调试过程又要反复追问,同一个用例被多次计费。其次是上下文窗口被挤占。你把页面结构、历史代码、业务规则全塞进去,真正决定代码正确性的那几行断言反而没有位置了,模型容易被整体逻辑带偏。最后是交付节奏。全 AI 生成的整段脚本看起来完整,但进入调试阶段就像在解谜,你分不清哪段是它根据真实结构写的,哪段是凭空编的。

所以我一直认为,现阶段指望大模型“看一眼需求就交付一套能直接跑的 UI 测试”不现实。现实的做法,是把 AI 用在它最擅长的局部补全上,而不是全局生成。

1.2 人工录制到底省下了什么

Playwright codegen 做的事情很简单:打开一个浏览器窗口,你在页面上点击、输入、选择,它在旁边把对应的代码一行行录下来。这个过程消耗的不是 Token,而是你的操作时间。但它换来的东西很值钱:真实的选择器、真实的跳转路径、真实的等待时序。

省 Token 的核心就在这。人工录制得到的代码不必重新生成,AI 要做的不是“无中生有”,而是在已有的骨架上补断言、补超时、补异常处理。这类补全任务的输入可以非常短:只给一个函数体、一行需求说明、一个输出约束。一次调用的 Token 量可能只有全量生成的五分之一。

另外,人工录制还有一个隐性好处:操作过程本身就在替你理解业务。你亲眼见过页面上哪个环节容易卡、哪里会弹窗、哪里加载慢,录制时自然会把信息带进 prompt。AI 从零生成时,它连页面长什么样都不知道,自然无从判断该等哪些元素、该断言什么内容。

1.3 这样的工作流适合谁

如果你只想写几条冒烟脚本验证页面没有白屏,全 AI 生成也能凑合,不太需要这套流程。但如果你的场景是下面这几种,建议把“录制 + 补全”用起来。

一是回归用例特别多,需要长期维护。这类脚本改一次可能影响一串用例,每一步逻辑都要能被人工快速理解。二是页面交互复杂,涉及多角色、多状态、多环境,AI 很难凭空想象出这些分支。三是团队对 Token 成本敏感,希望在享受 AI 辅助的同时控制开销。四是测试脚本要交给不太懂前端的人维护,人工录制降低了理解门槛,补出来的代码也更好读。

说白了,这套玩法解决的是“AI 能写但写不靠谱、人工会点但点得累”的矛盾。让人的操作能力去弥补模型的瞎猜,让模型的理解能力去弥补人的重复劳动。

2. 环境准备与整体流程设计

2.1 工具链与版本选择

Playwright codegen 本身很好起步,但版本差异会导致录制产物不同。我建议把 Playwright 版本固定下来,至少在依赖里锁住,不要放任 latest 乱跑,否则今天录出来的语法下个月可能就变了。安装方面一条命令就能完成,但有一个细节要提醒:codegen 用到的浏览器内核最好提前装好,不要等第一次录制时临时下载,网络一抖动很容易卡住。

项目语言方面,Python 项目就用 pytest-playwright 插件,Node 技术栈就用 @playwright/test。两套都能跑,关键是不要混用。团队内部统一一种,录制出来的代码格式才能被后续的 AI 补全模板复用。如果你在代码补全阶段接的是本地部署的模型服务,也要确认它能识别你用的语言语法,尤其是 Python 的缩进和 TS 的类型声明,模型在这两类语法上的表现差别很明显。

2.2 从录制到落地的五步流程

我的流程固定为五步:拆用例、人工录制、切片段、AI 补全、回放验证。

拆用例是第一位的,把业务场景拆成可独立验证的原子动作。比如“登录并进入列表页”和“创建一条记录并校验出现”就拆成两条,不要录成一坨。人工录制时只负责操作主路径,不处理断言和异常。切片段是把录制结果按函数边界切开,每个函数只解决一个动作。AI 补全时再给片段配上等待、断言、异常处理。回放验证就是真实跑一遍,看能不能连续过几次。

这个顺序不能乱。很多人习惯先写好 prompt 再开工,结果发现录制出来的代码和 prompt 里假设的结构对不上,白折腾。正确顺序是先录后补,让录制的实际情况决定补全内容,而不是让补全需求反过来约束录制方式。

2.3 目录与职责划分

还要在工程上把角色分开。我习惯建一个 tests/ui/ 目录,下面区分 recorded、completed、helpers 三个子目录。

tests/ui/ recorded/ test_create_user.py completed/ test_create_user_validated.py helpers/ auth.py waiters.py data_factory.py

recorded 目录存放 codegen 原始产物,基本不手改;completed 目录存放经过 AI 补全并且人工确认过的脚本;helpers 目录放公共方法,比如登录态处理、随机数据生成、元素等待工具。

这个分法最大的好处是让 AI 补全有明确边界。每次向 AI 提问时,可以直接说“参考 helpers 里的 wait_for_table 函数,补全以下片段”,AI 拿到的上下文更小也更精准,Token 自然省下来了。更重要的是,出问题的时候你能快速判断是哪一层的锅:原始录制有问题,还是 AI 补全有问题,还是公共方法设计得不够通用。

3. 核心实操:从录制到 AI 补全的完整步骤

3.1 用 codegen 录出可靠的骨架

启动录制很简单,在项目根目录执行命令:

npx playwright codegen --target=python -o tests/ui/recorded/test_create_user.py https://example.com

--target 指定生成语言,-o 指定输出文件。命令执行后会同时弹出两个窗口:左边是浏览器,右边是 codegen 检查器。你的每次点击、输入、跳转都会实时生成对应代码。

这里有几个实操要点。第一,尽量在真实的业务操作环境录制,不要在本地点两下就交差,否则录出来的选择器到测试环境根本对不上。第二,操作要放慢,每做一步就等一下页面加载完成,不要连续快速点击。codegen 在快速操作时容易漏掉中间状态,导致录出来的代码缺少等待。第三,录制过程中看到明显不稳定的选择器,比如带随机 ID 的 div,当场换一个固定的属性,别指望后面统一修改。

录制完成并不等于结束。我习惯把录出来的原始代码从头到尾读一遍,重点看有没有多余的 page.goto,有没有对同一个元素反复 click,有没有录进了非业务操作的鼠标移动。这些多余的代码在进入 AI 补全前清理掉,后面 model 的输入更干净,生成结果的噪音也少。

3.2 切片段:把录制产物拆成 AI 可补全的最小单元

codegen 的输出通常是一段很长的线性代码。直接把整段丢给 AI 是最省事的做法,但不推荐。因为片段越长,AI 改动整个结构的可能性越大,出幻觉的面积也就越大。

我习惯按操作语义切片段。一个典型的创建用户用例,至少切成三段:打开页面并登录、进入创建弹层并填表、提交并校验结果。每一段对应一个函数,比如:

def create_user(page, name): page.click("#create-btn") page.fill("#name", name) page.click("#submit")

这个片段只包含主路径,没有等待、没有断言、没有异常处理,正是留给 AI 的补全空间。切的时候要保持函数的单一职责,不要一个函数里既填表又校验列表又做截图。函数越短,补全时的 prompt 越短,Token 消耗越可控。

很多刚接触这套流程的人会问,切这么碎会不会增加维护负担。我的经验是不会。因为补全完成后,每个函数都可以独立回放、独立调试,失败时定位到具体函数,比在一段 200 行的脚本里翻找要快得多。

3.3 Prompt 模板与 Token 控制技巧

把常用补全指令固化成可复用的 Skills,是这套玩法里最关键的一环。我这里说的 Skills 并不是某个平台的专有功能,而是一组团队内部统一维护的 prompt 模板。只要你每次补全都按照同一套模板写,AI 的行为就会稳定很多,Token 消耗也能提前估算。

举一个“添加等待并补断言”的模板例子:

补全 create_user 函数,只输出缺失的行,不要重写整个函数。 要求: 1. 点击 create-btn 后等待弹层出现,再填充 name 2. 填充后点击 submit 3. 点击 submit 后等待成功提示文本包含“创建成功” 4. 如果表单校验失败,抛出带页面截图的错误 代码: {这里放置录制好的片段}

这段 prompt 的输出约束非常明确。要求“只输出缺失的行”这句话很关键,它是在告诉模型:你的角色是补全,不是重构。这样一来,模型不会把整段代码重写一遍,输出 Token 自然被压下来了。

Token 控制还有一些细的技巧。第一,放入 prompt 的片段控制在 50 行以内,超过 50 行就再往下拆。第二,不要在 prompt 里要求模型解释它在干什么,直接要输出。第三,明确告诉模型“不要返回 markdown 代码围栏和额外说明”,否则输出里会混进一堆没有用的格式字符。第四,如果模型需要理解某个 helper 函数,只贴这个函数的签名和一句话说明,不要把这个函数完整实现丢进去。

我把不同补全场景的 Token 消耗做过一次粗略统计,大致如下:

场景输入 Token输出 Token合计
全 AI 从零生成一个用例3000~60001000~20004000~8000
录制 + AI 补全一个函数400~800100~300500~1100

这只是同一个用例体量下的大致范围,不同模型的编码习惯会让数值浮动,但整体量级说明录制的方式确实能省不少 Token。

3.4 回放验证与断言补全

补全完成的脚本不能只停留在“看起来对”,必须真实回放。我的命令通常是:

npx playwright test tests/ui/completed/test_create_user.py --repeat-each=2 --workers=1

--repeat-each=2 表示同一个用例连续跑两遍,--workers=1 表示串行执行。第一次跑的目的是看脚本能不能完整走通,第二次跑是看它能不能经受住重复执行的考验。很多一次性通过的脚本,第二次跑就挂在登录态残留或者数据重复上。

断言补全也要有讲究。AI 生成断言时倾向于断言“元素可见”,比如等待某个按钮出现后 toBeVisible。但这类断言只能证明页面没崩,证明不了业务正确。一条有效的断言应该是“创建成功后列表第一行出现该用户,且状态为启用”。所以人工复核的重点是:AI 补的断言是不是对应了真实的业务结果,而不是页面表象。用 Playwright 的 web-first 断言可以自动等待,不要轻易在生产脚本里加 sleep,等待条件写在目标元素的状态上,脚本的健壮性和执行速度都会好很多。

4. 常见问题与排查实战

4.1 选择器时灵时不灵

回放时最常见的错误是找不到元素,最头疼的是这次能过、下次就挂。这类问题八成出在选择器上。codegen 默认记录的是 CSS Path,遇到动态 class 或者被前端框架二次渲染的 DOM,选择器路径就容易失效。

我的对策分三步。第一,能用 getByRole 和 getByText 就不用长 CSS Path,它们更贴近用户的真实视角。第二,跟前端约定,关键交互元素统一加>name: add_wait_and_assert description: 给已有片段补等待和断言 template: | 补全 {function_name} 函数,只输出缺失行,不要重写整个函数。 要求: {requirements} 代码: {snippet}

Skills 不是写一次就不动了。每次有人在使用过程中总结出新的踩坑点,就往模板里加一句约束。比如“不得新增定位器”“不要返回 markdown 围栏”“等待条件放在用户可见状态上”等等。两周更新一次,补全一次通过率会明显提高。

维护时还要注意语言差异。Python 和 TypeScript 的模板不能共用,因为两个语言生态里 Playwright 的写法差异不小。混用模板会让模型输出格式很乱,也会浪费大量解释成本。

5.3 我的一些个人习惯

最后分享两个我一直在用的小习惯。第一,不管 AI 补全得对不对,我坚持把每次回放的结果截图保存。出现问题时直接翻截图,比从日志里猜状态要快得多。第二,每周花半小时整理本周 AI 补全中出现的错误,挑三条高频问题更新进 Skills。这个动作听起来很小,但积累了几个月之后,补全的一次通过率会有一个很明显的提升。

踩过几次坑之后,我越发觉得,UI 自动化不是要把人赶走,而是让人只做最需要判断力的那部分。AI 负责把判断变成代码,人工负责录路径和看结果。省下来的 Token 其实只是副产品,真正省下来的是返工成本,是那些翻来覆去改脚本、反复跑用例却不知道哪里崩了的深夜。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询