在ui自动化中,与接口自动化中区别最大的是,ui自动化追求的是脚本的稳定性,那么如何保证脚本的稳定性呢?归根到底,就是元素定位的表达式,元素定位表达式稳定了,才能更好的保证ui自动化脚本的稳定性。本片文章主要针对于xpath元素定位表达式
一:绝对不要使用绝对路径的xpath表达式
1-- 面试的时候,面试官问你,怎么样做元素定位的?什么?绝对路径?好了,面试基本凉了
2-- 就算侥幸面试通过,真的需要你在工作中做ui自动化,在元素定位的时候,如果使用了绝对路径的表达式,那么恭喜你
解锁了新技能"前端手一抖,测试改一宿"。另外在工作中,要是遇到了有同事使用绝对路径的元素定位,视情况,可以婉言相劝,毕竟,皆为测试仔,相煎何太急~~
那么,要怎样才能写出较为稳定的元素定位表达式呢?
二:xpath相对路径表达式
既然有绝对路径,就有与之对应的相对路径表达式,接下来讲一下关于xpath相对路径的使用。
1-- 首先,先详细的介绍下xpat元素定位的语法。
//ul[@data-ul-id="convert"]/li//a
先简单分析下,上面的表达式。
1 ,//表示相对于前面的节点,如果//在最开头,则表示于相对于整个html,意思是:相对于整个html页面中,找到标签为ul的元素
2,第二个//表示相对于//ul[@data-ul-id="convert"]这个表达式找到的元素,是有层级关系,一层层找下去的。
3,/表示子节点,必须是直系节点,可以参照九代单传来理解。不在开头的//,则表示所有子孙节点,无须直系亲属,只要是子节点都包含。切记!!!
三:常见的xpath元素定位表达式
1://标签名[@属性名="值"] ---定位元素的属性
2: //标签名[text()="值"] ---定位元素的文本
3://标签名[contains(@属性名,"值")] --元素属性名中包含某些值的
4: //标签名[contains(text(),"值")] --元素的文本内容中包含某些值的
与第三例相同,不在举例。
5;层级定位。主要表达式。//祖先节点//要找的节点
//ul[@data-ul-id="convert"]/li//a 解释-- 通过比较稳定的属性,data-ul-id 找到ul,然后这个元素的子节点是li,li的子节点是a,从而找到了要找的元素,转化跟踪
6:轴定位 --元素的兄弟姐妹,父母
轴运算;
1- ancestor --祖先节点,包括父节点
2- parent --父节点
3-- preceding-sibling 当前元素节点标签之前的所有哥哥姐姐节点
4-- following-sibling 当前元素节点标签之后的所有弟弟妹妹节点
5-- preceding 当前元素节点标签之前的所有节点,没有层级关系
6 -- following 当前元素节点标签之后的所有节点,没有层级关系
注意 ,3,4,5,6指的顺序,都是相对于整个html页面的先后顺序
轴定位的使用语法-- 已知元素/轴名称::标签名[@属性='值']
//div[contains(@class,"money_overplus")]//span[text()="剩余:"]/following-sibling::span[1]
其中 ://div[contains(@class,"money_overplus")]//span[text()="剩余:"] 为已知元素
following-sibling:: 为轴名称
span为标签名
[1]表示前面的表达式能找到两个元素,现在取第一个
轴定位主要的应用场景,页面显示未一个表格样式的数据列,需要通过组合来定位元素,具体灵活,想要熟练掌握,需要多加练习。
7,逻辑定位
and
eg -- //div[contains(@class,"login") and text()="立即登录"]
//div[contains(@class,"login") and .="立即登录"]
注意:.可以代表text()
or
//div[contains(@class,"login-btn") or .="立即登录"]
not
//year[not(.=2005)]
意思是:查找year内容不为2005的内容 注:“.”就等于text()
非: !=
//div[contains(@class,"money_overplus")]//span[text()="剩余:"]/following-sibling::span[.!="万"]
当定位到//div[contains(@class,"money_overplus")]//span[text()="剩余:"]/following-sibling::span 时有两个元素,这个时候可以通过下标取值,也可以通过非查找取值,哪个稳定用哪个!
四:怎样写出更加稳定的元素定位表达式呢?
1, 元素定位表达式尽可能的简洁,条件越少,定位越稳定
举例:找到24.66
复杂表达式-- //div[contains(@class,"money_overplus")]//span[text()="剩余:"]/following-sibling::span[1]
简单表达式:
//span[@class="mo_span4"]
从对比中可以总结出,我们在写元素表达式的时候,原则一定是从简到繁,能写简单的表达式定位到元素,就不要写复杂的,只有简单的定位方式定位不到的时候,再去考虑,通过逻辑,通过轴定位去定位。
2 -- 善用组元素 备注(这里是从jack大佬的文章中引用过来的,详见链接:http://testingpai.com/article/1595507202464)
组元素,即通过一个表达式可以定位出一组元素。有些时候,并不是能唯一定位到元素的表达式就是好的表达式,根据业务需求,善于利用一组元素,也可以大大减少我们元素维护工作,看例子:
如图是一个修改密码的页面,如果按照常规套路,唯一定位出三个输入框的元素,表达式如下:
//input[@placeholder="Current Password"]
//input[@placeholder="New Password"]
//input[@placeholder="Confirm Your Password"]
那么请同学们仔细观察这个页面,主要操作元素都是输入框,我们何不利用表达式定位出一组元素,再通过取 index 的方式去操作元素呢?那么元素表达式写成一个 //input
即可,这样写,随便迭代时属性值怎么变化,input 标签总归不会变吧,一个 input 标签能用到离职都不用维护。
通过下标取值的操作:
//input[1] --找当前密码元素, //input[2] --找当前新密码元素 //input[3] --找确认密码元素
再次声明,(这里是从jack大佬的文章中引用过来的,详见链接:http://testingpai.com/article/1595507202464)
3:多使用contains,定位,不管元素属性还是元素文本。找准了关键字,使用模糊匹配,能匹配到就使用模糊匹配。后期维护就没有那么苦逼了。
后续会继续完善~小菜鸡漏油~