出处:「哔哩哔哩技术」公众号 《基于数据沙箱与LLM用例自愈的UI自动化测试平台》
原文地址:https://mp.weixin.qq.com/s/oygl1dPGLtoyz0sldz4Erw
本文摘出了其中使用 LLM 的部分,可以学习其落地方式,用于自己项目。侵删。
方案
当页面发生迭代后,哪怕从功能上看此次迭代与某用例无关,却往往会导致该用例脚本失去作用,需要被更新。比如元素class改变、元素位置改变、元素内容文本改变等。
可以想象一下,在人工回归时,大部分情况下我们“聪明的人类”能轻松地识别出变化后的目标元素,那么能否让UI自动化测试拥有接近人类的目标元素识别能力呢?
一个最显然的方案是:基于图像识别选取元素。这原本也几乎是唯一最佳选择,但随着近几年LLM的迅速发展,我们想到了另一种可能:基于LLM实现目标元素智能识别。毕竟最新LLM模型的文本理解能力已经相当惊人,而“页面结构”本身也是通过文本(dom)进行描述的。因为对图像识别相关经验不多,且第二种方案也有望扩展至“目标元素智能识别”以外的各种场景,故选取了第二种。
该方案大致为:在用例执行中,若selector获取失败,则暂停执行,将页面dom、selector等信息交由LLM进行处理,让其识别出该“过时的”selector真正想获取的元素是什么,返回更新后的selector路径,然后更新相应用例并重新执行,达到“用例自愈”。
DOM压缩
在将信息输入LLM前,有一个很明显的问题:页面dom可能会很大,导致LLM处理时间很长,甚至可能直接超过LLM支持的大小上限。比如这是b站首页渲染完成后的dom大小:
高达22万tokens!不过其中大部分信息对“目标元素识别”来说都几乎是无意义的,我们可以将它们全部删除,进行“dom压缩”:
- 删除script、style、link等结构无关tag
- 空格、换行合并
- 对于剩下的所有tag,仅保留tag、id、class、text信息,其它全部删除
经过这些步骤后,该页面占用的tokens大幅降低至1.3万:
可剩下的dom中重复内容还是不少的。比如某个class名可能在页面中出现很多次,占用了很多字符。所以可生成一个”class压缩映射表“,把每个class名映射为一个数字,最终可能用0-500这些数字就能表示所有class名,当然,数字每位”密度“还是太低了(只能包含10个不同的值),且class名开头不能为数字,所以用字母”计数“更佳,比如先从a到z,再+1就是aa,以此类推,大部分class名都会被压缩至两个字符以内(经过试验,仅此步就可将该页面tokens数进一步降低至0.9万)。
同理,tag名称也可压缩。甚至”class“这个字段本身也可压缩(比如压缩成”c“)。
经过这些压缩后,dom确实会继续缩小,然而这些压缩会丢失不少”有语义“的信息,无论是一些class名(比如”task-btn“)还是tag名,它们有助于LLM去理解页面内容、做出更准确的目标元素识别,所以我们最终未选择这些进一步压缩的方式(另一种方式是将压缩映射表也告知LLM,不过也会提高LLM理解难度,有待试验)。
实际上,b站首页算是b站dom最庞大的页面之一了,大部分页面经过第一步的压缩后,tokens会远低于1.3万(比如很多移动端页面压缩后tokens数为1500-5000)。
Prompt
压缩完dom后,便可以构造promot了,我们的prompt结构大致如下:
其中会先通过一些例子让LLM学会如何进行“模糊匹配”(即根据“不准确的selector”找到正确的元素),然后将压缩后的dom、selector交由它完成任务。
对于实际效果,我们进行了一些初步试验:
在一般情况下,“用例自愈”能力已可满足要求(仍在优化中)。对于确实变化很大难以“自愈”的,将提示用户重新录制用例。
执行流程
采用标元素智能识别与用例自愈后的执行流程如下:
Fine-Tuning?
目前我们对LLM的所有要求都被囊括在prompt中,这可能并不是最佳方式,毕竟prompt的长度有上限,我们无法灌输给LLM足够多的信息去提高正确率,也会消耗较多处理时间和费用。
而fine-tuning允许我们根据自己的特定需求和数据集来定制和优化模型,以适应特定场景,相比上面的纯prompt方案,我们可以预先喂给大模型多得多的“模糊匹配”例子,进一步提高其识别目标元素的能力,且prompt大小可大幅缩减(prompt中“前置能力学习”的部分可以去掉了)。所以fine-tuning应该是更好的方式,由于当下时间有限暂未尝试,后续会深入。