乐于分享
好东西不私藏

【实测】UI自动化用AI断言页面源码怎么搞?(上)

【实测】UI自动化用AI断言页面源码怎么搞?(上)

    前言:更着更着面试题,怎么突然写这个了?大家不要觉得突兀,实测系列文章内容均为学员或粉丝实际工作中遇到的技术难点,这些问题各位工作中估计都用的到,先收藏一波等用的时候直接找到!
    今天要聊的技术点是各位做UI自动化时候,比如用selenium也好,用playwright也罢,总之进行页面断言的时候问题。
    以前的时候,我们是等每一个操作步骤之后,精确的断言一些关键点,如某元素是否可见,如某文案是否出现。而定位这些元素的方式大多是id、name、text、xpath、class等等。
    这种方式有几个缺点:
  1. 误报:断言过于死板,一旦元素发生变更就会误报。
2. 漏报:断言不够全面,毕竟整个页面元素众多,你只断言三俩个元素的个别属性,很容易漏报bug。
3. 成本高:开发成本、维护成本大,需要自己去写代码,一旦前端更新,就要重写,不更新不用重新,但也不需要测。一更新就重写代码的时间不如手动测了。
4. 无高科技含量,在ai火爆的当下, 这种方式显得过于low了。
所以,咱们搞个AI断言,AI的好处之一就是节省人力成本,既然都没啥人力成本了,那干脆让AI来个全页面全元素断言吧!
    这里面的难点不在于技术实现,而在于把控平衡点。毕竟页面有变化了,你通过算法对比就可以发现不同,但不代表页面它bug了对吧。而且源码中有很多关于js等代码也没太大必要去断言。用户肉眼看的就是元素的外观和位置还有一些是否可点击可编辑的属性等等。
    这些东西通过算法其实也不是完全实现不了,甚至很久之前我已经搞定了,但总归还是Low了,毕竟AI兴起了,我们就把AI融合进来,看看能干点啥就干点啥把。这次文章直接把这个功能给大家搞明白。
注意,本功能点文章内容较长,所以分为【上中下】三篇。
大体流程
页面前段框架千万万,但最终呈现在眼前的,都是浏览器看的懂的,看起来就是原生的元素。你vue的组件元素也是经过翻译变成原生的展现在浏览器上的。而AI断言时候看的就是原生元素,比如<button> 就是<button>,而不是<el-button>。那我们准备用来开发这个功能的页面就一个就可以了。
具体流程如下:
  1. 准备一个空白html页面,往上面添加任意一个元素。
  2. 开发简单的断言模块,用算法成功获取页面源码和比对,包括生产结果等。
  3. 不断给空白页面添加更多元素,并且进行各种修改。
  4. 不断给断言模块测试,丰富其断言能力代码。(该断言细节较多,并不一定符合所有公司项目风格,所以我准备给做成可简单修改定制的)
  5. 带智能体进场,让智能体根据结果判断页面是否出现bug。
  6. 设计反馈优化通道和人工评审环节,让智能体不断精确衡量标准。
  7. 使用公开的真实页面进行测试,持续无限的优化下去。
  8. 其他再说
需要注意的是,整个断言模块需要做到高内聚独立,便于推广和使用,还有就是速度上必须要快,毕竟断言是自动化过程中一个比较常见的步骤,过于耗时肯定是不行,所以这就是为什么我不是很推荐用AI视觉解析,那太慢也太耗成本了。只有当元素发生变化找不到了没办法的时候再调用,这也是以后我会更新的一个篇章《AI前端元素变化自动维护》系列的内容了,有兴趣的先关注然后催更把~
为了方便粉丝们观看实际前端变化效果,所以本教程会做成能渲染出实际页面的,而非全是源码的。所以为了便于渲染前端页面,我使用了较为简单的django,这样方便编写前端和修改等。获取页面源码使用了selenium的库。小伙伴们不用刻意去跟着写,毕竟对新手搭环境还挺麻烦的,感兴趣的话就看看后面的断言部分代码即可。
好,我快速搭建了一个用来开发调试这个模块的django,并且初始化完毕,目前可以正常打开第一个页面:
接下来开发简单的断言模块骨架:
模块文件名称:AIasset
模块主类名称:Aia
第一个功能函数:get_html 用来获取页面的html源码。
这个get_html的实现咱这得说说,正常工作中,大家是通过自动化工具比如selenium打开进入到了该页面,然后可以顺势用selenium的driver.page_source方法直接拿到,但我这为了调试方便和快速,总通过selenium有点太慢了,于是就直接用python自带的方法通过url拿源码也一样。等后面实现完成了再改回selenium或者其他工具的方法。
运行看看输出效果:
上面增加了一个状态码断言,如果页面打开后状态码不对,可以直接报错,当然后续的反馈记录bug渠道应该会捕获并记录这个状态码异常问题,效果如下:
接下来我们要获取页面的所有标签元素,需要使用bs4库,自己pip3 install bs4下载吧。
这里我用一个列表装下来所有元素标签的名称、属性、文案。
但这里有个值得思考的点,其实我可以继续获得元素的层级关系,比如父元素是谁,子元素是谁,兄弟元素等等。但是考虑到这样下去计算量太大了,加上在获取文案的时候,注意到里面那一堆\n了么?那个其实一定程度上已经可以代表层级关系了,就是兄弟元素和父级包含内部所有子元素的换行或者空白text,如果出现层级错误,那么这些\n数量和位置也会发生变化,利用这个小巧思,我们可以节省大量运算。前提是千万别给元素去重,不要多此一举,那样层级关系就找不到了,这个小妙招可是一般人不会教给你的哦。
(这里其实还有个后续升级的功能,就是利用selenim获取更多元素的信息,除了名称、属性、text外。还有元素位置、大小、坐标、中心点、是否可见、是否可用、是否选中、css效果等等。这貌似才是判断元素是否正常的终结效果。本文只给大家提供这个升级思路,大家可以自行尝试加入进去。或者之后报名我以后的【新版AI前端自动化测试平台课程】受平台化的大型基建能力,这个完整版的AI断言模块能更好的嵌入进去)
接下来,我们要写一个保存函数,断言断言嘛,你没有特么标准答案,怎么知道最新获取的页面是正确的呢?
我们应该在某一次的没有bug的情况下,调用保存功能,让这次的所有页面所有元素结果保存到标准答案库中,方便后续对照。
问题来了,我们是保存完整页面html文件,还是保存解析后的all_data列表数据呢?很显然,你单独保存完整页面html的话,后续还需要每次再解析一次才能对比,而且单独页面保存本地后和网站失去连接的话也会导致各种加载失败,所以这里很明显必须保存解析后的all_data数据。
那标准答案的身份应该如何证明呢?
如果用现在存储页面的url,这能证明身份么?哪怕是同一个页面,因为你操作不同,导致页面变化,你又多次断言这个页面,那url肯定是不能代表的。
所以,我们要存入标准答案的时候,能证明身份的东西就只有一个,就是id。
写具体自动化脚本的时候,需要断言的时候,需要把标准答案的id带进去。要知道哪一步用哪个id的标准答案,当然写死一次后也不用再改了。日后需要更新标准答案的时候,只需要给AIassert模块传入个参数,让其不启动对比断言功能,而启动保存覆盖功能即可。
所以接下来我们要写的俩大功能函数就很明确了:
begin_assert(断言) 和 begin_update(更新)
最后思考一个问题,保存标准答案的话,通过什么媒介呢?
是数据库?还是本地文件夹?
欢迎小伙伴进去讨论,具体如何留到下一节中。
别忘了一键三连,关注,转发,点赞哦!
本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » 【实测】UI自动化用AI断言页面源码怎么搞?(上)

猜你喜欢

  • 暂无文章