文章目录
一、Selenium的缺点分析
常用的Web自动化测试方法往往都是基于元素定位的方式来进行的,比如热门的selenium、appium都是基于这种方式的。
但随着react
、vue
的普及,以及element
、antd
等组件库的出现,,通过元素定位的方式就显得有心无力了!
为什么这样说呢?我们举一个简单的例子来说明:
下面是通过antd
组件库来实现的一个小Demo,页面有两个个按钮:【添加用户】、【修改用户】:
它们会打开编辑用户资料的弹窗的弹窗,弹窗里他们都有两个相同的【确认】按钮。
我们知道,通过元素地址来定位元素的第一要点就是这个元素有唯一标识,当然有些小伙伴会说,直接通过Xpath
路径定位不用唯一标识也能定位到!
这里先不做解释,我们一步一步来分析,告诉你为什么不建议使这么做!
如下图所示,这两个确定按钮的元素地址无论标签、文本信息、还是class都是完全一样的,因为都来源antd
组件库的同一组件。所以它们没有任何区别!
正因为它们没有唯一的标识,所以如果想通过id
、class
、甚至是xpath
的contains
方式来定位,selenium识别不了到底是哪一个按钮,就会失效!
当然,也正如上文说到的,通过xpath路径的定位方式也可以定位成功,就算没有唯一标识也行。
但会带来什么样的影响呢?还是举个例子告诉你:
我们先打开添加用户的弹窗,获取【确定】按钮的xpath
地址:
/html/body/div[2]/div/div[2]/div/div[2]/div[3]/button[2]
然后再打开修改用户弹窗,获取它的【确定】按钮的xpath
地址:
/html/body/div[3]/div/div[2]/div/div[2]/div[3]/button[2]
可以明显的发现:它们的div
层级不一样,一个是div[3]
一个是div[2]
,其他都是一样的。这样能够执行成功,也能区分出两个按钮!
但是,如果你先打开的是【修改用户】的弹窗,那它的【确定】按钮所在的div
层级就不是[3]
了,会变成[2]
!!
这样就与【添加用户】弹窗的【确定】产生了冲突,他们的元素层级都在div[2]
了,当你再次执行时就会出现问题!在我们编写自动化测试脚本的时候,不可能一番风顺,总会因为各种原因出现一些问题,慢慢修改解决,一次次重跑才能解决!但正因为这样的操作,以及元素路径地址的不确定性,会大大加大我们的工作量!
而且必须按照预定的顺序执行,对于上述的场景中,我们的执行顺序必须是先打开【新建用户】的弹窗,再打开【修改用户】的弹窗,如果顺序反了,就会定位失败!
另外,前端调整页面,哪怕微调,也可能导致相关模块的整个UI用例全部需要重写!
一点维护性都没有,还谈什么高效?
在网上也有小伙伴提出了类似的问题:
它们的解决方案是让开发加上id来解决。但实际上开发是不会情愿去为了方便你做自动化测试来加id的,因为会增加它的工作量。即便开发愿意加入id,我们的工作量依然很大!
首先,上述的两个【确定】按钮的样式和标签等信息都是一样的。但你还是需要写两个元素地址来区分他们,如果一个弹窗嵌套的比较深,还有二级弹窗、三级弹窗,那你就需要写多个【确定】元素地址,这依然很麻烦!
在我实际的项目中,有一个嵌套多层的弹窗,它的确认按钮就有7个!
那有没有只用一个元素地址,也不用让开发加唯一标识就能解决这些问题呢?
肯定是有的,不然我也不会写这篇文章了!
二、解决方案
1. 讲解与演示
我们可以使用图像识别来定位它,比如网易团队开源的airtest
,类似于上述弹窗嵌套有多个【确定】按钮的情况,我们只需要截取一张【确定】按钮的图片,就能解决无数重复的确定按钮的定位了!
这是我通过截图-图像识别的执行效果:
两个【确定】按钮完全共用的是一张图片
2. 实践教学
现在跟着我一起从0开始利用airtest
写一个简单的图像识别测试脚本吧
需求
编写一个程序,它会通过图像识别执行点击百度的【新闻】,然后点击【互联网】这两步操作
具体步骤
1.先安装airtest
pip install airtest -i https://pypi.tuna.tsinghua.edu.cn/simple
2.创建一个项目,并输入如下代码:
from airtest.core.api import *
news_path = 'news.png'
internet_path = 'internet.png'
connect_device('Windows:///')
ST.CVSTRATEGY = ["surf", "tpl"]
ST.FIND_TIMEOUT = 2
touch(Template(news_path))
touch(Template(internet_path))
3.先打开百度截取【新闻】图片,再点击新闻,截取【互联网】图片:
截取的图片如下,命令为news.png
并保存到代码所在目录
截取的图片如下,命令为internet.png
并保存到代码所在目录*
4.检查目录文件命名是否与代码中一致
5.让浏览器保持百度访问
6.执行代码然后马上切换回浏览器,执行效果如下:
完全脱离了元素地址的方案进行自动化测试,并且无论上Web还是App,甚至PC应用都能够兼容!
三、依然存在的问题
在使用中可能会发现,分辨率不同,截取的图片就用不了!如果被测机器的分辨率都不相同,那是不是就得需要多套图片呢?
其实airtest
针对此问题也有一些解决方案:
- 更改识别算法 (本人亲测,效果不好!!)
- 通过重写官方代码来实现适配分辨率的图片压缩方法
- 更改识别相似度阈值
另外airtest
也有不可忽视的缺点:
- 被测对象必须保持可见(无法隐藏浏览器进行)
- 界面有相同元素时无法定位
所以airtest
和selenium
相结合才是目前最好的选择!