[UI测试]元素定位方式总结

前言:
我们知道,UI 自动化测试最基本的功能就是如何定位元素并进行接下来的点击、输入、验证等操作;从另一角度来看,UI 自动化测试用例是否稳定,关键也要看你的元素定位是否合理,健壮、可靠的元素定位策略可以保障测试成功率的提高,经过一段时间的基于Cypress的UI自动化实践工作,发现用例失败的90%的原因应该就是元素定位失败导致的,而且目前业务大部分使用vue. react等框架,遇到开发升级框架组件等,一定会大修一次元素定位,因此为减少一部分维护成本,总结下一些元素稳定定位方式。而以下方式基本是基于Cypress该自动化框架,但思想应该差不多通用。

一、元素定位方式总结

1.id定位

  • 概念:通过元素的id属性来定位元素
  • 前置:所要定位的元素必须要有id属性
  • Cypress通过id定位: cypress.get(‘#id’)
    该方式无需多说,因为id具有唯一性,定位准确快捷,无须遍历dom

2.class定位

  • 概念:通过元素的class样式定位元素
  • 前置: 标签必须有class属性
  • 特点: class属性可以有多个值 & 重复
  • 提示:如果标签有多个class值,只能任意选择其中一个
    现在大部分业务都是使用vue react等框架,因此很多样式都是框架自动生成和命名的,遇到
    框架升级,有可能所有元素的均定位失败,因此尽可能避免使用class定位

3.tag定位

  • 概念:根据的标签名进⾏定位,例如:input form table
  • 提示:如果⻚⾯存在多个相同标签,默认返回第⼀个
  • cypress中通过tag定位: cypress.get(‘input’) 、 cypress.get(‘table’)
    在经典Selenium中,一般不建议使用tag定位, 因为标签可能有太多重复,例如div标签,一个页面可能有几十个。但在cypress中可以链式调用,所以我们可以结合需要定位元素的父元素/子元素/相邻元素进行辅助查找。例如:
    在如下表格中我们需要定位第二条数据的添加按钮,此时该按钮无id,并且每条数据的按钮都是框架生成的样式,因此无法使用id或样式定位。但这个页面可能只存在一个table, 因此我们通过标签可以很容易定位到table:
    cypress.get(‘table’),通过table可以定位到第二行,通过第二行又可以定位到最后一列,在最后一列中我们直接cypress.get(‘button’),就能获取到第二条数据的添加按钮,代码如下:

在这里插入图片描述

cypress.get('table').get('tr').eq(1) //查找table的第二行,index从0开始计算
.get('td').last() // 查找table的第二行的最后一列
.within(() => {    
cy.get('button') 
// 查找table的第二行的最后一列中的button按钮。
})

web端的系统,大多都是表格、表单等,这种通过tag定位元素的方式不受样式等影响,是比较稳定的定位方式之一
4.xpath定位
当我刚开始搞cypress自动化时,听一位同事说可以使用xpath定位,由于当时不怎么会学习, 没有仔细学习xpath定位方式,直接在浏览器进行copy xpath / copy full xpath,然后当遇到一次业务UI改版,发现xpath定位的基本全失败,这让我一度让我在自动化的MR里无知的和其他同事说: 在咱们自动化项目里绝对不要出现xpath定位,但仔细看了下xpath定位方式后,发现他跟上述tag定位有异曲同工之妙,先上正确用法:

表达式描述
nodename选取次节点的所有子节点
/从当前页面的跟路径开始遍历查找
//从匹配选择的当前节点选择页面中的节点,不考虑位置
.选取当前节点
选取当前节点的父节点
@选取属性

首先,介绍一下xpath的路径节点表达式,如:
表达式描述nodename选取次节点的所有子节点/从当前页面的跟路径开始遍历查找//从匹配选择的当前节点选择页面中的节点,不考虑位置.选取当前节点…选取当前节点的父节点@选取属性

  • xpath绝对定位:严格按照元素顺序,过于依赖当前页面元素结构,不稳定,最开始就使用的copy full xpath,让我一度误会了xpath的方法 ,cy.xpath(‘/html/body/div[1]/div[1]/div[5]/div/div/form/span[1]/input’),缺点就是当整个页面有一个元素变化了或新增元素,就又可能造成大部分元素定位失败
  • xpath相对定位:灵活、用法多、建议用,根据元素本身特征查找、不用按特定顺序.包含以下这些方法:
  1. 单属性定位:
    //标签名[@属性名=属性值]
 cy.xpath('//div[@role='dialog']')
  1. 多属性定位: 使用and or关键字
    //标签名[@属性名=属性值 and @属性名=属性值]
cy.xpath('//div[@role='dialog' and @id='country'] ') // 表单弹窗中找到country输入框
  1. 文本定位:
    //标签名[text()=“文本”]
 cy.xpath("//button[text()='提交']")
 4.  文本与属性值组合:

//标签名[text()=“已签到” and @class=“tip”]

cy.xpath("//button[text()='提交'  and @disabled='true']")
  1. 模糊查找-contains
    //标签名[contains(text(),“文本”)]
cy.xpath("//*[contanins(text(),'提交' ) ]
  1. 完全模糊查找
    //[XXXX] //[text()=“提交”] //span[@=“提交”] //[@*=“XXX”]

  2. 层级定位,也就是通过3种链式条用的方式
    7.1. 通过父或者祖先找子元素 (经常用到),通过自己本身的特征无法唯一定位自己的时用层级定位。格式:

语法
//父标签[@id=“u1”]//子标签[@name=“tj_login”]

7.2 轴定位:通过子元素找祖先元素

语法
已知元素//…//…/轴名称::标签名[@属性名=“属性值” and @属性名=“属性值”]//…

轴名称:

名称描述语法
parent:父元素 – 通过子找父 (找到子元素再父)//子标签名[@属性名=“属性值”]/parent::父标签[@属性名=“属性值”]
ancestor::通过子找祖先元素//子标签名[@属性名=“属性值”]//子元素标签/ancestor::父标签[@属性名=“属性值”]
preceding-sibling::通过当前元素 找姐姐/哥哥元素(同一父元素,排在当前元素前面的)//标签名[@属性名=“属性值”]//标签/preceding-sibling::标签[@属性名=“属性值”]
following-sibling::通过哥哥姐姐找弟弟//标签名[@属性名=“属性值”]//标签/following-sibling::标签[@属性名=“属性值”]
  1. 属性定位
  • 概念:通过元素的特定属性定位
  • 前置:通过属性查找也应该和id一致,使用唯一数据定位
  • Cypress通过属性定位:
cy.get('[title="XXXX" ]'

例如:下面这种日期选择,就可以通过属性定位,其中title属性对应到某一天,这个属性就是唯一的,不会重复
在这里插入图片描述

conststartDate = '2022-12-16'
constendDate = '2022-12-17'
cy.get('[title="'+ startDate + '"]').click({ force: true});
cy.get('[title="'+ endDate + '"]').click({ force: true});

6.键盘辅助
在写用例时,发现有一种情况的元素很难定位,即下拉框中的内容
在这里插入图片描述

上图中:由于是框架生成的,每个选择框的元素的样式都是一样的,并且下拉框中每个选项样式又是一样的,也没有其他特定属性,我们很难定位到下拉框&下拉框中的选项
这时候我们可以使用键盘辅助,例如我每次均选择第二个:

cy.get('contentTag').click().type('{downarrow}{enter}') // 点击输入框唤起下拉框,然后键盘向下选择,enter选中

当然,很难定位的元素比较少,遇到以上情况可以尝试下键盘辅助操作。

二、思想总结

看了一篇文章,觉得思想上写的和我实践过程中遇到的感想非常相似,也用自己的话解释下这个大佬的思想:

​1.大道至简​​
大道至简指的是有明显特征的元素一定要用明显的特征去定位。此处特别强调一下,不一定是只有id是明显特征,有时候当前页面只有一个table,那table也就是明显特征,可以直接get。

2.​分而治之​​ & 由大到小
一般页面层级是非常清晰的,当没有明显特征的时候,一定要善用层级定位,也就是把页面可以划分为几个区域,例如在表单中查找,在table中查找,甚至在小一点,我在某个表格的某一行的某一列内进行查找

​ ​​3.酌情而定​​
定位最怕在一棵树上吊死。当你一种方式不行的时候就要视情况换一种方式。下面是我一个刚开始做自动化的同事的反馈,当我们遇到很难定位的时候可以换一种思路,日常多积累些稳定定位的方法,遇到比较难定位的可以逐一尝试

​ ​4.动静结合​​

有些元素是有特殊属性的,但是这些属性是动态变化的。这时候我们就要想办法去获得动态属性,例如上边讲到过的定位日期,这里的title就是动态的,我们可以通过写一些逻辑,获得动态属性,再去进行查找

conststartDate = '2022-12-16'
constendDate = '2022-12-17'
cy.get('[title="'+ startDate + '"]').click({ force: true});
cy.get('[title="'+ endDate + '"]').click({ force: true});

​ 5.​殊途同归​
所有方便、逼格较高的定位方式,都是殊途同归,只要能够优雅的定位(不要用机器自动生成的xpath)到元素,一切方法和手段都是等价的,不管黑猫白猫,能稳定抓到元素的就是好猫!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值