模糊用例智能解析:让AI驱动的自动化测试更加可靠
发表日期:2026-04-10被浏览: 12次返回
模糊用例智能解析:让AI驱动的自动化测试更加可靠
很多团队在做 AI 生成 UI 自动化用例时,第一反应都差不多:把自然语言测试步骤一股脑丢给大模型,让它直接输出关键字驱动脚本。
这个方向在 Demo 阶段通常能跑通,但一进真实业务环境就会暴露问题:原始用例并不精确,上下文信息并不完整,字段约束也不统一,而大模型又天然倾向于“补全”信息。结果往往是结构看起来完整,细节却并不可靠。
在我们的搭建平台的实践中发现,真正困难的不是“让 AI 生成步骤”,而是让 AI 在不确定时保持克制、在推断时留下依据、在无法确定时把决策权交还给人。
这篇文章想讲的,就是我们如何把一个“一把子生成”的方案,重构为一套更适合生产环境的模糊用例智能解析架构。
问题不在生成,而在失控
如果只看表面,模糊测试用例到自动化步骤的转换,似乎只是一个文本生成任务。但实际落地后,我们遇到的核心问题并不是“模型不会写”,而是“模型写得太像真的了”。
比如一条常见的业务用例可能只有几句话:
登录系统,进入报表模块,查询上月数据,验证结果正确。
对人来说,这段话已经足够清楚;但对机器来说,里面几乎每个字段都有歧义:
如果把这些空缺都交给大模型自由发挥,它确实能给出一个完整答案,但完整不等于可靠。它可能来自原文提取,也可能来自截图推断,还可能只是依据常识脑补。问题在于,这几种来源的可信度完全不同,但在最终结果里往往看起来一模一样。
此外,很多测试描述其实是复合动作,例如:
搜索上海到北京的下周五航班,并筛选中转次数为零的结果。
这句话至少可以拆成导航、填写出发地、填写目的地、选择日期、点击搜索、设置筛选条件、执行结果校验等多个原子操作。一次性生成时,大模型对粒度的判断非常不稳定:有时拆得太粗,多个动作混在一步里;有时又拆得过细,生成出大量并不必要的操作。
归根到底,这不是模型单点能力不足,而是系统边界定义得不够清楚。把“理解”“约束”“决策”三件事都交给同一个模型,是最根本的失控来源。

从“一把子生成”到“职责分离”
后来我们调整了思路:不再要求大模型一口气完成全部工作,而是明确划分三类职责。
-
LLM负责理解。它负责分析测试语义、识别字段、做有限推断,并说明每个字段是怎么来的。
-
规则引擎负责约束。它负责校验模型输出、修正不符合约束的字段,并以确定性规则生成用户问卷。
-
用户负责拍板。凡是模型无法高置信确认的部分,最终都由用户明确确认或补充。
这听起来像是在“给 AI 加限制”,但实际上恰恰相反:只有把概率性能力放在它适合的位置上,AI才真正能在生产环境里稳定工作。
在这个思路下,整个流程被重构为五个阶段:
1. 页面匹配:为步骤召回可能相关的页面与截图
2. 页面确认:由用户确认页面绑定是否正确
3. 一体化分析:多模态 LLM 结合文本与截图做字段解析
4. 规则后处理:校验来源、修正字段、生成问卷
5. 最终确认:用户回答问题后,系统确定性生成结果
这里的“页面匹配”是整条链路的地基。我们的做法是先从页面库做向量粗召回,把候选页收敛到top-15,再结合页面描述和截图做重排序,而不是把第一次召回结果直接喂给模型。

这个流程里最关键的变化有两个。
第一,用户不是最后才被迫“兜底”,而是在两个关键节点参与低成本确认。在模型分析前,先确认页面绑定对不对;在模型分析后,只针对低置信字段做定向确认。这样既保留了效率,也避免了让用户对着一整张步骤表做地毯式审核。
这背后其实对应的是一种很明确的人机分工:系统优先消化大部分可以通过文本、截图、上下文和规则收敛的问题,只把最后剩下的真正无法确定的部分交给人拍板。关键不在于“让人工参与”,而在于把人工参与压缩到最值得介入的地方。

为了保证这种分工在工程上可控,整个流程本质上是一个受状态约束的会话流,而不是几次松散的接口调用。我们在编排层用统一的<code>FuzzyParseOrchestrator</code>驱动整条链路,用Redis CAS保证状态迁移的原子性,再通过两次SSE 推送把“页面确认”和“分析结果”分阶段返回。这样处理的意义不只是在代码上更工整,而是为了应对重试、并发和断线恢复:前端重连时,不应该重复触发 LLM;用户回退修改页面绑定时,也不应该污染已经完成的后续状态。真正进入生产环境后,这类边界处理往往比“模型那一步写得多聪明”更决定系统稳定性。
第二,最终结果不再由模型“再生成一次”。一旦进入用户确认阶段,后续合并全部由规则完成,不允许模型在最后一步重新脑补。
这里还有一个经常被低估、但实际上非常影响系统可信度的细节:规则后处理不是简单“洗一遍数据”,而是真正的质量闸门,它至少做三件事:
第一,做<code>extracted</code>校验。也就是当模型声称某个字段“来自原文”时,系统不会直接相信,而是会回到原始步骤文本做程序化核对。只要原文中找不到对应表达,这个来源就会被自动降级,而不是允许模型把推断伪装成提取。

但如果这里只做严格字符串匹配,又会带来另一个问题:自然语言本来就不是按关键字表写出来的。测试人员可能写“填写用户名”,系统关键字却叫<code>输入</code>;可能写“验证结果”,系统内部却对应<code>断言</code>;还可能写“跳转到报表页”,而平台动作名是<code>打开页面</code>。如果把这些都判成“不在原文中”,系统虽然看起来更严,实际却是在错杀有效信息。
所以我们在<code>extracted</code>校验里加入了别名映射机制。系统维护一张可持续扩展的同义表达表,把“填写/录入/输入”“验证/校验/断言”“跳转/进入/打开页面”这类自然表达映射到统一动作语义。只要原文命中这些别名,系统仍把它视为来自原文的有效信息,保留<code>extracted</code>这一最高可信来源。更重要的是,这张映射表不是硬编码在系统里的黑盒规则,而是可以持续维护的配置能力,后续能够按业务习惯逐步扩展。它不是放宽标准,而是在不牺牲严谨性的前提下,承认真实用户语言的多样性。

第二,做字段约束修正。不同关键字对字段的合法性要求并不相同,例如点击动作通常不需要测试数据,而对于输入操作测试数据则是必填项。规则引擎会基于关键字约束表强制修正这些不适配字段,避免模型把“结构完整”误当成“字段越多越好”。

第三,做问卷生成。哪些字段需要问、用什么方式问、是否给候选项,全部由规则决定,而不是再交给模型临场发挥。这也是为什么后面的用户确认可以既轻量又稳定。

一个关键设计:
让每个字段都带着“来源”出现
为了让模型输出变得可解释,我们引入了一套字段来源标注机制。简单说,就是要求模型在输出每个字段值时,必须同时回答:这个值到底是从哪里来的?
我们把来源分成五类:
|
来源类型
|
含义
|
典型场景
|
|
直接提取(extracted) |
直接从原始步骤文本中提取
|
原文明确写了“上海”“点击登录”
|
|
<code>截图推断(screenshot_based)</code> |
从页面截图可见信息推断
|
截图里能看到按钮名、输入框标签
|
|
<code>上下文推断(context_based)</code> |
结合标题、上下文、前后步骤推断
|
上一步已进入报表页,本步默认仍在该页面
|
|
<code>常识推断(common_sense)</code> |
基于通用业务常识推断
|
登录通常需要账号密码
|
|
<code>未知(unknown)</code> |
无法可靠推断,必须人工补充
|
原文和截图都没有提供足够信息
|
这套机制的价值,不只是“多了一个标签”,而是它把原本黑盒的生成过程变成了一个可审计的推断链。

而且 SourceType 在这里不是纯展示字段,它本身就是一个可参与决策的结构。不同来源拥有不同可信度:直接来自原文的字段权重最高,其次是截图可见信息,再往后才是上下文推断和通用常识,<code>unknown</code>则意味着系统必须停止猜测。这个顺序不是为了“显得严谨”,而是为了在后处理和最终合并时建立一条明确纪律:系统只能从高可信来源向低可信来源退让,不能把低可信推断包装成高可信事实。
换句话说,<code>common_sense</code>永远不能覆盖<code>extracted</code>,<code>context_based</code>也不能伪装成“来自原文”。一旦原文和推断冲突,原文优先;一旦截图和常识冲突,可见证据优先。这条看似简单的优先级铁律,实际上是抑制幻觉最有效的工程手段之一。
例如,模型说某个操作目标是“登录按钮”,如果它标成<code>extracted</code>,系统就会进一步校验:原文里是否真的出现了对应表达?如果没有,来源就会被自动降级,而不是允许模型把自己的猜测伪装成“来自原文”的事实。
也就是说,我们不是单纯相信模型的自我声明,而是把“来源标注”本身也纳入校验对象。这一步对抑制幻觉非常有效。
更重要的是,来源标注并不是只给系统看的内部元数据,它还直接参与前端交互。一个真正可用的系统,不该只是默默计算置信度,而应该把这份判断以低成本方式暴露给用户。我们把不同来源类型做成清晰的视觉标签,并在悬浮时展示判断理由,让用户不用逐格猜“这是不是AI脑补的”。高可信字段可以快速略过,低可信字段则天然吸引注意力。



这看起来只是一个Tooltip级别的小功能,但它实际上改变了用户的审核方式:用户不再需要在整张表里逐格猜测哪里靠不靠谱,而是在系统已经完成风险分层的前提下,有选择地审查最可能出问题的部分。这样一来,用户需要关注的就不再是全部字段,而只是系统明确告诉你的那一小部分“不确定区域”。
为什么补充问题不能让模型自由生成
很多人会觉得,既然已经用了LLM,那补充问题也让它一起生成不是更自然吗?
我们一开始也这么做过,但效果并不好。原因很简单:问卷不是创作任务,而是约束任务。
对系统来说,问卷承担的是“把所有待确认信息完整、稳定、无遗漏地抛给用户”这一职责。它追求的不是语言灵活,而是结构稳定。只要同样的输入会产生不同的问题集合,下游交互就会变得不可预测。
更具体地说,我们最早的交互形态其实不是“问卷”,而是“把模型输出整张表摊给用户,让用户自己找不确定项并修改”。这种方案看起来灵活,体验却很差。用户需要逐行扫描字段、自己判断哪里值得怀疑,再决定是改值还是保留。系统本来应该承担的“识别不确定性”,被转嫁给了用户。
后来我们把这个模式彻底改掉:用户不再对着整张表做排查,而是顺着系统提出的问题逐项回答。这看似只是交互形式的变化,实际上是职责边界的再次落地——系统先完成风险定位,再把真正需要拍板的少数问题交给人。
这里有一个很关键的设计选择:我们没有把问题都做成自由填写,而是大量采用“选择优先,输入兜底”的方式。这个思路借鉴了 很多当下流行AI 编程工具在规划阶段处理不明确需求时的交互范式:当系统已经能收敛到几种合理方案时,最好的体验通常不是让用户从零描述,而是直接给出候选项,让用户点选、修正或补充。像Qoder、Roo Code、OpenCode这类工具之所以交互顺手,很大程度上就在于它们不把“表达成本”全部压回给用户。

我们把这种范式迁移到了测试用例解析里。
-
当某个字段属于<code>context_based</code>时,意味着模型已经有较强倾向,但仍可能需要人确认;这类问题最适合做成确认题,让用户快速判断“就是它”还是“需要修改”。
-
当某个字段属于<code>common_sense</code>时,意味着存在多个都说得通的解释。这时如果仍要求用户手填,实际上是在浪费模型已经完成的推理工作。更好的做法是把模型给出的最可能值和备选值一起呈现出来,并始终保留“其他/手动输入”作为兜底。这样既利用了模型的推理能力,又不把它的判断当成最终事实。
-
只有在<code>unknown</code>场景下,也就是文本、截图、上下文和常识都不足以支持可靠判断时,系统才应该明确承认“这里我不知道”,并把问题转成必须填写的开放项。
这套问题分发逻辑可以概括为:
-
<code>context_based</code> → 确认题
-
<code>common_sense</code> → 候选项选择题
-
<code>unknown</code> → 必填开放题
看上去这只是一个问卷分类规则,但它实际上深度影响用户体验。因为它把“哪里该思考、哪里只需确认、哪里必须输入”区分开了。用户不再需要在每个字段上都切换到同样高强度的思考模式。
同时,问卷生成完全由规则引擎根据SourceType确定性驱动,而不是再调用一次模型。这意味着对于相同的分析结果,无论何时、重试多少次,生成的问题数量、问题类型和交互结构都保持一致。生产系统里,这种可预测性比“偶尔问得更聪明”更重要。
多模态不是锦上添花,而是必要条件
如果系统只看文本,不看页面截图,那么很多字段其实永远无法进入高置信状态。
测试用例里常见的描述往往是“点击查询”“进入详情页”“选择日期”,这些词在人类语境里没有问题,但对模型来说缺乏具体UI锚点。页面截图提供的价值,不是替代文本,而是把这些模糊动作落到具体界面上:按钮长什么样、页面当前处于什么区域、有哪些可见控件、相邻元素之间是什么关系。
因此我们采用的是一体化多模态分析:先由页面匹配模块为步骤召回可能相关的页面与截图,再由用户确认绑定关系,最后把文本+页面上下文+截图一起送进同一次 LLM 调用中完成结构化分析。

这里我们刻意控制了 LLM 的调用次数。整个流程只在核心分析阶段调用一次大模型,后面全部由规则引擎接管。这样做有两个现实收益:
为了把这一次调用用在刀刃上,我们会严格控制注入上下文的结构和预算:系统提示负责定义字段约束、来源标注和输出格式,用户提示负责承载当前步骤文本、页面上下文和截图说明;相似历史用例只做少量受控注入,最多参考 3 条;截图也不是越多越好,真正有效的是与当前步骤强相关的少量页面,因此我们会把截图数量限制在可控范围内,而不是把整套页面库一股脑塞进去。
很多 AI 系统的问题,不是单次调用效果差,而是串联了太多次“都还不错”的模型调用,最后整体变得不可控。减少调用次数,再加上严格的上下文预算控制,本身就是一种工程上的稳定性设计。
这套架构真正解决了什么
从结果上看,这套方案并没有神奇到让AI完全自动替代人。它解决的是一个更现实、也更重要的问题:让AI生成的内容第一次具备了生产可用的可信边界。
这种“可信边界”并不只体现在分析阶段,还体现在最后的结果落地阶段。我们明确规定最终值的合并优先级是:用户手动修改>问卷确认结果>LLM原始推断值。也就是说,模型给出的答案永远只是候选,不是最终事实。
同时,系统还会在最终生成前计算“完整率”和“可信度”这类质量指标:前者反映关键字段是否填满,后者反映当前结果中高可信来源占比如何。它们未必直接决定能不能生成,但会决定系统是否应该提醒用户复核。我们不把“能产出一份结果”当成功,而是把“能带着清晰质量状态产出结果”当成功。

具体来说,它至少带来了四个层面的提升。
1. 可解释
每个字段不仅有值,还有来源和理由。用户看到的不再是一份“AI 说是这样”的答案,而是一份“AI 为什么这样判断”的答案。
2. 可追溯
系统可以记录每个字段的原始推断值、最终采用值、来源类型、推断理由以及用户是否介入修正。这为后续评估模型质量、分析误差模式提供了非常扎实的数据基础。
这也是为什么我们非常强调把字段来源映射、修正记录和最终归因持久化下来。对于一个生产系统来说,真正有价值的不是“这次生成成功了”,而是下次当它出错时,你能不能准确回答:错在页面匹配、错在模型理解、错在来源误判,还是错在用户确认前的信息缺失。只有这些轨迹被保留下来,系统才具备持续优化的可能。
3. 可控
模型只负责分析,不负责最终拍板;规则只负责约束,不负责主观判断;用户只在必要处介入,不需要从头重写。三者边界清楚后,系统行为才真正变得可预测。
4. 可扩展
一旦来源标注、字段约束、问卷规则这些基础设施建立起来,后面无论是引入相似历史用例、强化页面匹配、补充关键字别名映射,还是扩展更多业务场景,本质上都可以在现有框架上迭代,而不需要推翻整体设计。
一个更值得复用的经验
回头看这个设计,最有价值的经验其实并不是某个具体功能点,而是一条更通用的原则:
在AI工程里,不要试图让模型替你定义系统边界。模型应该工作在边界之内,而不是边界本身。
测试用例解析只是一个具体场景,但类似的问题在很多 AI 产品中都存在:需求不完整、上下文不充分、输出必须可审计、结果不能靠“感觉差不多”。在这种场景下,真正决定系统上限的,往往不是模型参数量,而是你是否把概率能力、确定性规则和人工决策组织成了一条合理的协作链。
结语
模糊用例智能解析这套方案最核心的价值,在于:它不是试图让LLM一次性解决所有问题,而是用严格的工程约束驯服了LLM的随机性。
我们没有把“理解、约束、决策”全部交给同一个模型,而是把整个转换流程拆解为职责清晰的多个环节:页面匹配负责快速定位上下文,LLM负责语义理解与字段推断,规则引擎负责质量兜底,用户确认负责填补AI的知识盲区,最终的确定性合并器负责保证输出的一致性。
SourceType 五级标注机制是这套架构的核心纽带。它不仅是LLM输出的质量标签,也是规则引擎决策的依据、问卷生成的触发条件、置信度计算的量化基础,以及用户审核时的视觉导航系统。正因为有了这套贯穿前后链路的来源纪律,系统才真正具备了“可解释、可追溯、可控”的生产特性。
从结果上看,这套设计真正完成的,不只是把一段模糊描述转成一组关键字步骤,而是把AI在测试用例生成场景中的实际可用性,从“概念验证”推进到了“生产可信”。
对UI自动化测试来说,这比一次漂亮的生成结果更重要。
欢迎投稿
感谢原文作者的精彩分享,内容极具价值。欢迎大家投稿交流,共同维护专业知识阵地。通过审核的优质稿件🌟我们会第一时间联系。
投稿邮箱:yue.guo@cstqb.cn
投稿方式:CSTQB公众号投稿-“姓名”-“稿件名称”
投稿内容:(含需投稿文章+联系电话+个人简介+CSTQB®考试证书持有情况。)