
我在前东家带测试自动化项目那几年一直有个执念让业务同学也能写自动化用例。为了这个目标我试过录制回放工具、关键字驱动框架、BDD行为驱动开发那一套Gherkin语法结果无一例外都死在同一个地方——业务同学写完第一版之后再也不想碰第二次。直到去年开始把大模型引入到用例转脚本这条链路里我才真正感觉到AI把自然语言变成测试脚本这件事不是简单的“旧活新干”。它解决的是无代码测试发展这么多年一直没跨过去的那道坎让机器理解业务语言而不是让业务人员迁就机器语言。这篇文章把我们从原型验证到小范围落地的完整经历拆开讲讲包括原理、选型、踩坑和团队分工变化希望能给同样在观望的测试团队一点参考。别误会我不是来推销什么“万能AI测试神器”的。相反你会发现我对AI生成脚本的态度谨慎得很。因为真正跑过之后才知道自然语言转测试脚本最核心的价值不在“生成代码”那一步而在上下文理解、元素定位、结果解释这一连串看起来不起眼的环节。这些才是决定它能不能从玩具变成生产力的关键。1. 折腾过几年“低代码测试”的我为什么这次觉得AI真的不一样1.1 录制回放和关键字驱动当年都卡在同一个地方先说说老办法。录制回放大概是不少团队第一次接触“无代码测试”的入口工具记录你在页面上的操作自动生成一段脚本。听起来很美好业务同学只需要像平时操作一样点点点。但凡是维护过这种脚本的人都知道页面结构稍微调一下按钮位置挪一挪脚本就全线阵亡。更糟的是录制产生的脚本充斥着大量无意义的坐标、层级和等待时间一个简单操作能生成几十行代码出了问题根本不知道从哪看起。后来行业里开始推关键字驱动把“输入用户名”“点击登录”这类动作抽象成关键字业务同学通过填表格的方式拼装测试步骤。这个思路比录制回放进步了不少因为至少动作是语义化的可读性提高了。但问题也很快暴露关键字库的维护变成了新的技术债每新增一个复杂组件都得找测试开发去封装新的关键字。业务同学看似在“填表写用例”实际上仍然是在一套受限的编程语言里表达自由度很低。折腾到最后写用例的依然是测试人员自己所谓无代码只是把代码换成了另一种难用的配置。BDD是另一条路。用Given When Then的格式写场景让产品、开发、测试都能读。说实话这个表达方式比关键字驱动更贴近自然语言。但落到具体执行时每一句自然语言背后还是要有一层step definition去映射到代码。维护这套映射的人还是测试开发而且Gherkin写久了大家都会发现它变成了“半自然语言、半代码”的奇怪混合体为了能被步骤定义匹配语序、词汇都不能随便换等于换了一种方式写代码。这些工具之所以都没能真正普及到业务侧归根到底是一个原因它们都缺一个能够把自由语义转换成可执行步骤的智能解释层。业务人员输入的是“人话”但工具希望输入的是“半结构化的人话”这个要求本身就是巨大的心智负担。1.2 AI补上的其实是“从业务语言到代码语言”的翻译层大模型出现后我第一次感觉到这个翻译层终于有了着落。你直接写“用户使用管理员账号登录进入客户管理页点击新增客户保存成功后列表出现刚才的客户”模型拿到这句话能够主动把句式拆分、补充动作缺失的上下文、映射到页面元素然后生成一条可以执行的测试脚本。它不需要你按照某个固定模板去说话也不需要你理解CSS选择器是什么更不需要你去维护一个关键字库。为什么这次的体验和以前完全不一样因为以前我们是在“穷举表达方式”让用户从我们预先定义好的几种说法里选现在模型是在“理解表达方式”理论上它能接受无穷多种合法句式甚至能处理指代和省略。打个比方录制回放像让一个不懂业务的演员照着剧本笨拙地演关键字驱动像让业务人员填一份审批表而AI转脚本像是请了一个懂业务也懂代码的中间人听完需求后自己把分镜画好、台词写清楚。这个变化对测试团队的意义不是“省了几个写脚本的人力”而是把自动化测试的入口从测试工程团队扩展到了整个业务团队。需求说清楚的那一刻执行脚本已经有了草稿。后面的章节我会具体讲这条链路里模型是怎么运作的以及哪些环节需要人来兜底。2. 一句“登录后点击保存”背后AI到底做了什么2.1 它不是翻译是一层层重构意图识别先于代码生成很多人以为自然语言转测试脚本就是把中文句子塞给大模型让它直接输出一段Python或者JS代码。实际工程里这样做非常容易失控因为代码生成是结果而不是过程。我们第一版原型就是这么干的模型输出脚本的质量完全取决于句子长度、复杂度和模型当天的心情。后来我们把转换过程拆成了两步先做意图识别与动作序列化再做代码生成。第一步模型把自然语言解析成一个结构化的动作列表每个动作包含操作类型、操作对象、输入数据、预期结果第二步基于这个动作列表去生成对应平台的执行代码。这个中间层非常重要原因有两点一是可控如果模型把动作理解错了我们在看到代码之前就能发现二是可解释业务同学确认的是一步步的动作描述而不是扑面而来的代码块。举一个实际例子输入“用测试账号登录打开订单列表把第一笔订单的状态改为已发货”。模型输出的中间表示大概是这样的[ { action: open_url, target: 登录页面, data: {} }, { action: input, target: 用户名输入框, data: {value: test_account} }, { action: input, target: 密码输入框, data: {value: test_pwd} }, { action: click, target: 登录按钮, data: {} }, { action: click, target: 订单列表菜单, data: {} }, { action: click, target: 第一笔订单的状态列, data: {} }, { action: select_option, target: 状态下拉框, data: {value: 已发货} }, { action: verify_text, target: 页面提示区域, data: {value: 操作成功} } ]这一步看着平平无奇却是整个流程的灵魂。因为一旦有了结构化动作列表后面不管是生成代码、生成报告还是让人工审核都变得异常轻松。模型出错的地方也会集中暴露在动作层方便我们针对性修正。2.2 上下文补全AI是怎么看懂“它”指的是哪个按钮自然语言和编程语言最大的差异在于人说话时会大量使用指代、省略和依赖常识。业务同学写的完整用例还好一旦写得不严谨比如“点击保存后它提示成功”这个“它”可能是提交按钮也可能是页面里的某条记录还可能是弹窗。如果模型不理解上下文生成出来的脚本就是随缘点击。我们在系统里做了两层上下文补充。第一层是会话上下文把当前用例之前的操作步骤、当前页面路径、页面内可见的按钮和输入框清单都作为背景信息喂给模型。这样当出现“它”的时候模型可以通过最近的锚点名词推断出指代对象。第二层是页面DOM结构上下文在生成脚本时模型会先读取页面里可交互元素的语义属性列表把它当作“候选人池”再让模型从池子里挑选与自然语言描述匹配的目标。举个例子用户输入“在上一步打开的弹窗里点击确认”。“弹窗里的确认按钮”和页面底部工具栏的“确认保存”按钮是两个完全不同的元素如果模型手里有DOM结构信息就不会选错。这套机制在落地时非常依赖页面语义属性的质量。如果开发团队完全没有测试标识模型就只能靠按钮文字猜准头会差很多。后面讲选型和坑的时候我还会详细展开。2.3 元素定位与自动修复脚本能跑的关键不是语法而是找得对自然语言转测试脚本的过程中代码生成不是难点元素定位才是。因为代码语法错了编译器会告诉你但脚本跑挂大概率是被测页面某个按钮找不到或者定位到了错误的元素。最早的模型输出脚本特别喜欢生成这种定位器html body div:nth-child(3) div div.col-lg-6 button。这种选择器在生成的当下是能跑的但页面任何一个前序节点变化它就崩了。我们把元素定位策略从“生成固定选择器”改成了“生成语义描述兜底定位策略”。也就是模型为每个待操作元素生成一组候选定位方式按优先级排列首先是data-testid其次是aria-label或placeholder再是按钮文本和元素类型组合最后是视觉坐标。执行器拿到这组候选后依次尝试一旦匹配成功就锁定。如果全部失败才判定为脚本需要维护。真正的杀手锏是自愈机制。脚本执行失败后我们不是直接报错而是把当前的DOM可交互元素列表、失败元素的语义描述、页面截图一起交给模型让它重新推测目标元素现在在哪里然后自动修正定位器再跑一次。这个功能看起来很玄学但实际成功率相当可观对于页面文案调整、按钮位置移动这类常见变更AI能准确重新找到目标。当然自愈也不是万能的如果页面彻底重构模型也救不回来那时它会诚实告诉我们找不到对应元素需要人工介入。这套机制让无代码测试第一次有了一点“越跑越稳”的底气。3. 小团队一周上线“白话测试”流程我踩过的选型和落地方案3.1 我最终选的技术组合与理由先交代一下背景我们的被测系统是某公司一个跨多个端的业务平台前端组件库内部统一页面结构相对规范但业务规则复杂回归测试量大。团队里除了我和另一名测试开发其余测试同学基本只会写SQL和手工用例。因为大模型生成代码的环节非常关键我一开始就在商业服务和开源模型之间纠结。商业模型的效果确实更好但我们会把业务描述和页面结构送到外部服务这在很多公司过不了信息安全评审。最后选了本地部署的开源模型效果略逊一筹但胜在可控且可以把整个测试数据上下文放在内网里流转。执行层我们用了开源生态里的浏览器自动化框架但没用它的默认调用方式而是自己做了一层语义化执行器。这层执行器接收的输入不是普通代码而是刚才提到的结构化JSON动作列表。这么设计主要是为了屏蔽底层差异模型换版本、框架换API我们只需要调整映射层不用重写一套用例生成逻辑。整体架构分三块用例管理与需求描述模块、转译服务、执行器与报告模块。用例管理和报告模块都是现成平台改造出来的真正自研的只有转译服务这条线。3.2 一条中文用例从输入到报告的全过程讲一个我们跑通的最小闭环。业务同学在用例管理平台里新建一条用例标题叫“管理员能够新增普通客户”前置条件写“已使用管理员账号登录系统”步骤里写“点击左侧客户管理点击新增客户填写客户名称为测试公司A联系人小张手机号13800000000点击保存页面出现客户列表中包含测试公司A。”这条用例被提交后转译服务会先做预处理把它拆成前置条件和操作步骤然后组装页面上下文调用本地模型生成动作列表动作列表经过规则校验后映射成浏览器自动化脚本并开始执行。执行过程中每个操作都会截图留痕最终报告会显示每一步的操作描述和实际结果而不是一堆日志。下面是我们提示词模板里很关键的一段模型能不能稳定输出主要看这里你是测试用例执行器。根据给定的自然语言测试步骤输出JSON数组。 要求 1. 每个动作必须有action、target、data三个字段。 2. 操作对象必须是页面真实存在的可交互元素。 3. 如果描述中有输入值data.value必须写成具体值不得写“正确账号密码”这类模糊描述。 4. 预期结果用verify动作表示。 5. 不确定的元素优先标记为need_human_confirm严禁编造。 输入步骤{user_input} 页面可见元素列表{dom_context} 输出这个模板看起来简单但每一项约束都是踩过坑换回来的。比如第3条是为了防止模型把“正确账号密码”真的生成一个叫“正确账号密码”的字符串第5条是为了避免模型找不到元素时硬编一个假的选择器导致执行过程中才失败反馈极慢。3.3 反馈闭环确认按钮、失败截图和语义化报告自动生成的脚本直接扔去跑是没有意义的因为业务同学根本不信任机器。我们做的第一件事是在用例提交后增加一个“AI理解确认”环节。系统把模型生成的动作列表渲染成一个可勾选的步骤清单业务同学看到的是“打开客户管理页面”“填写客户名称为XXX”“点击保存”这些可读文本如果某个步骤理解错了可以直接修改然后让模型基于修改后的动作列表重新生成脚本。这个环节看起来多了一步人工操作但对整个流程的信任建立非常关键。我们把确认过的动作列表存成历史记录相当于每次执行都有一份人类和机器都认可的需求语义快照。测试同学在排查失败时不再需要从代码开始译而是从动作列表对比实际情况问题到底出在需求描述、AI理解、定位策略还是产品Bug一眼就能分清。报告端我们也做了改造。以前自动化测试报告是红红绿绿的通过失败列表业务同学基本不看。现在每个失败点都会附上当时的页面截图、模型定位目标的语义描述、实际匹配到的元素信息。比如报告会写“需要点击目标保存按钮实际找到页面底部一个文字为‘暂存’的按钮候选定位方式全部失败”。这种语义化报告让产品、开发、业务都能参与进来判断缺陷归属而不是只有测试看得懂。4. 真实项目里翻过的车能跑但不敢信是最要命的阶段4.1 生成脚本有随机性同一句话跑出两种写法第一个让我们非常头疼的问题是随机性。同一个用户、同一条用例、同一个模型上午和下午生成的脚本可能完全不一样。上午用的是按文本找按钮下午就变成了按data-testid找按钮。两种写法本身都能跑但造成了一个很现实的问题测试同学在Review代码时发现这条用例昨天审过了今天又冒出一个完全不同的实现审也不是不审也不是。我们摸索出来的解决方案是组合拳。一是把模型的采样温度调到很低让输出尽可能稳定二是给模型固定few-shot示例让它模仿示例的格式和风格三是在转译服务里加一层结构化输出校验要求模型必须输出合法的JSON且字段必须符合schema。这样做了之后同一句话在绝大多数情况下会产出同一个动作列表。偶尔还会变但已经从“全句重写”缩小到“个别措辞差异”Review成本下降了一个量级。更稳妥的做法是把每次确认过的动作列表缓存起来。同一用例在落库时就直接读取缓存的版本只有需求描述变更时才重新调用模型。这相当于把AI当成一次性翻译官而不是每次执行都重复翻译。说实话生产环境里跑得很稳定的那条路径最后基本都是这么处理的。4.2 页面文案改动按钮就找不到了如果说随机性是“能跑但烦人”那么元素定位失败就是“直接卡死”。有一次我们的页面上有个“批量导入”按钮开发为了业务需要改成了“导入数据”就一个词的差别当天AI生成的脚本全部挂掉。原因很简单模型的定位策略还是以文本匹配为主语义描述里写的是“批量导入按钮”页面上找不到完全匹配的文本于是败给了自己之前的理解。这件事给我们上了重要一课语义定位不能做成文本完全匹配要支持文本包含、同义词、功能描述匹配。后来我们会给模型提供更丰富的页面上下文比如元素的title属性、附近文本、所在表单区域并且要求模型在写语义描述时多写几个角度“打开客户列表的按钮”“导航菜单中名字包含‘客户管理’的链接”“工具栏上旁边有‘新增’文字的按钮”。这样即使主方案崩了备选方案还有机会命中。自愈机制在这里也有贡献。当某个元素定位不到时执行器会把当前页面上可交互元素的文本清单交给模型让模型重新判断哪个才是当初描述的目标。有一次某个按钮从“立即保存”改成了“确认提交”AI通过旁边的图标和表单结构猜到了对应的还是那个保存按钮自动更新了定位方式那一次我们没有人工干预它自己修好了。但我也得提醒一句自愈成功不代表用例可以完全放任不管还是要有Review机制盯着防止它把错误的元素当作正确目标。4.3 人际语境和机器语境的差距有些话AI真的接不住自然语言转测试脚本最大的讽刺在于自然语言本身往往不够“自然”。业务同学写“正确登录”我们和同事沟通时都懂这是用有效账号密码登录但模型不知道什么叫“正确的账号密码”它只会按字面理解然后编造一个占位符。更离谱的例子是“点击确定”业务同学觉得表单填写完了这时候点“确定”保存但页面上可能存在弹窗的确定、页面的确定、甚至一个不起眼的“OK”按钮模型经常选错。还有一类问题出在口语化省略上。人写用例时会写“输入金额然后点击计算检查税额对不对”。这里的“金额”没有具体值“税额对不对”也没有明确预期。这种用例让同事手工测没有任何问题但让AI转成脚本就是送命题。一开始我以为是模型能力不够后来发现是我们的输入规范没有跟上不能要求模型理解连人都没把前提说清楚的需求。为了解决这个问题我们总结了一套面向业务同学的“AI测试用例写作规范”重点不是让他们学技术而是学会把模糊的词换成具体的可验证表达。具体下面展开。4.4 我们总结的“AI测试用例写作规范”这份规范不是给测试开发看的而是给业务同学和测试执行人员用的。它不需要句句完美但需要满足几个基本条件。我把关键规则和示例对比放在一起写作要点推荐写法不推荐写法操作对象清晰点击左侧菜单中的“客户管理”点击客户管理那个链接数据指定具体值输入金额为999.99元输入一个合适的金额预期结果可验证页面出现提示“保存成功”检查是不是保存成功了避免口语省略点击“提交”按钮后在弹窗中点击“确定”提交后确定一下避免前后步骤混乱先打开订单列表再点击第一行的“详情”打开订单列表然后进入详情看看有人会问这不又变成结构化表达了和关键字驱动有什么区别区别在于这套规范只是“尽量遵守”不是“必须遵守”。模型能容忍一定程度的偏离实在写得不规范也能生成候选步骤只是会标出不确定项让人工确认。这比老办法那种“不符合格式就跑不起来”的模式宽松太多。5. 测试团队的分工被重构了不写脚本之后我们干什么5.1 需求澄清变成了最高优先级的测试活动无代码测试跑起来之后团队里第一个变化是写脚本的时间大幅缩水但需求讨论的时间明显变长。因为AI生成的测试脚本质量直接取决于自然语言用例所描述的业务预期是否完整。以前需求有歧义测试同学在写脚本的时候还能自己脑补补全现在AI不会脑补或者脑补得不对最后跑挂了拉一群人来看效率反而更低。于是我们干脆把测试活动往前移测试同学在需求评审阶段就要把验收场景写成自然语言用例。那些平时藏在测试工程师脑子里的边界条件、异常分支、数据前置都被迫变成显性文字。这一步刚开始很痛苦因为很多隐性知识说出来才发现漏洞百出但坚持两个月后开发和产品都开始习惯拿这份用例清单来对照实现需求澄清的质量肉眼可见地提升。这个转变的本质是测试人员从“写代码的人”重新变回了“设计测试的人”。AI接管了代码生成和元素定位的体力活人终于可以把注意力放回测试最有价值的环节——判断什么样的场景值得测什么样的预期才算合理。5.2 Review机制AI生成脚本必须经过“用例转译评审”团队一开始面对AI生成的脚本内部有很大分歧。有人觉得既然模型都写好了直接跑就行了不用看代码有人觉得不审不放心万一模型生成了一段“看起来能跑、实际在乱点”的脚本回归结果全是绿的反而埋了大雷。最后我们定下的流程是不审代码但审转译结果。所谓转译评审就是评审第二节提到的结构化动作列表。测试同学看的是AI把自然语言拆成了哪些动作、动作顺序是否正确、目标元素是否对应、数据值是否合理。这个评审几乎不需要懂代码但确实能抓住绝大多数模型理解偏差。每次评审通过后动作列表会被锁存后续执行都用这个确认版本直到需求描述有更新。有一个容易被忽略的细节模型生成的脚本里可能会包含超出用例描述的动作比如自动添加了一个“等待5秒”或“滚动到页面底部”。这类动作多半是为了执行稳定性加进去的没有坏处但评审页上必须明确展示让团队知道模型做了什么额外决策。否则有一天脚本里混进了一个“等待60秒”没人发现用例执行时间就会悄悄失控。5.3 无代码释放的是长期维护成本而不是执行人力关于无代码测试我一直有个观点它真正解决的不是“让业务同学也能跑自动化”这个面子问题而是“脚本维护成本失控”这个里子问题。传统自动化测试里需求一变用例文本和脚本代码双份维护改动成本极高而现在用例文本本身就能生成脚本机器理解的是最新语义人维护的只有一份自然语言描述。我们最直观的收益是回归用例的周转周期。以前一个版本迭代完成测试团队花一周补脚本、调定位器是常事现在大部分时间花在需求澄清和用例描述上生成脚本变成分钟级。人力释放出来之后我们开始安排测试同学去做探索性测试、竞品分析和线上问题复盘这些活动产生的价值比维护一堆脆弱的XPath高得多。但这不代表测试开发岗位会消失恰恰相反团队里最缺的反而是能把自然语言用例高效“喂”给AI、并设计Review兜底机制的人。这个角色要懂测试设计、懂一点模型边界、还得能跟业务顺畅沟通比单纯写脚本要难得多。6. 半年实践后的边界感哪些场景值得上AI无代码哪些别硬上6.1 我认为值得用和不该用的场景对比用了半年后我对这套技术路线的边界有了比较清晰的感觉。不是所有测试都适合交给AI转脚本硬上的后果往往不是效率提升而是团队对AI失去信任。我把适合和不适合的场景做了个对比供参考适合用AI转脚本的场景不适合用AI转脚本的场景业务回归用例操作路径稳定输入数据明确涉及实时音视频、白板协作等强状态交互页面结构规范有稳定DOM属性或语义化标签页面频繁重构且没有任何稳定标识的阶段用例需要业务人员进行需求确认和复查完全没人参与评审全自动跑批的环境短周期项目、快速迭代需要频繁调整回归范围高度复杂的多步状态机比如订单状态反复流转冒烟测试、核心路径巡检强视觉断言比如需要比对截图细节、动画效果我特别想强调“页面频繁重构”这个场景。如果一个前端团队正处于组件库替换期今天改一个按钮文案、明天换一个布局这时候让AI去生成脚本相当于让翻译员去翻译一本每天都在改写的书。你修好一个定位器页面又变了体验会非常挫败。这种时候更适合先把页面稳定下来再谈AI自动化不然挫败感会让业务同学觉得“AI也没有比老办法强多少”。6.2 下一步从单条用例生成走向场景编排和回归策略目前我们的落地还停留在单条用例的转换和执行下一步我想往场景编排方向走。因为真实业务很少是单个操作更多是一个连贯的用户旅程比如“登录-创建订单-关联客户-提交审核-查看状态”。AI如果能把整条旅程理解成一个带数据流转的场景自动把前一步的输出接到后一步的输入那才是真正的端到端无代码测试。现在已经有了一些探索。我们把自然语言描述里的业务对象抽出来比如“创建客户后拿到客户编号再用这个编号去发起订单”AI可以理解需要保存一个中间变量。这会比简单的动作序列化更进一步也给测试设计带来了更大的想象空间。回归策略也可以交给AI在需求变更时让它对比新旧用例描述圈出受影响范围进而建议本轮回归要跑哪些路径。这些方向还不成熟但至少让我看到这条路还有不少延伸空间。最后分享一个我们团队内部的小习惯每周把AI生成失败、自愈失败、人工修正过的用例集中收回来挑出典型样本扩充到模型的few-shot示例库里。这个动作看起来不起眼但坚持几个月后模型对团队业务术语的理解明显变好比如“客商”到底指的是客户还是供应商双击还是单击表单校验的提示文案长什么样它都越来越有数。我觉得这才是AI时代测试团队真正的核心资产——不是脚本库而是经过持续清洗和验证的“业务语义语料库”。