简单一定高效吗
UI自动化的元素定位有两种思路,第一种是直接利用Chrome开发者工具F12,在元素上邮件,菜单复制自动产生的XPath或者selector即可,第二种是自己动手写出高可读、生命周期长的漂亮定位表达式。
- 第一种自动产生的XPath/Selector,通常很长,并且可读性差。更加不妙的是,如果在UI
自动化测试用例中使用,当前端代码发生了小小的变动时,这个XPath/Selector也需要发生小小变动,方式就是再一次从页面上复制自动产生的XPath/Selector,对于测试用例维护人员来讲,投入的时间和精力成本就增加了不少。 - 第二种方式,提供了一个透过现象看本质的思路,在前端代码发生了不大变化时,测试用例可以直接批量修改甚至不需要调整。本文着重介绍第二种方式
XPath和CSS Selector
写好的XPath或者Selector,是否可以成功唯一定位到页面元素,是通过chrome的F12工具,ctrl+F后,输入框中填写XPath/selector查找。Selector的定位速度更快,写法更简洁。而XPath在通过文本定位方面功能更加强大(后面有详细介绍)。我们应该根据实际情况灵活选择。
Selector
Css selector常用写法整理如下
分类 | 符号 | 实际的例子 |
---|---|---|
id | # | <h3 id="learn-flink"> 用 #kw |
class | . | <div class="flex-even">用 .flex-even |
复合class | 用.连接 | <div class="flex-even markdown-inner">用 .flex-even.markdown-inner |
标签 | 无 | <input type="text"> 用input,重复率太高,一般要搭配属性一起用 |
属性 | [] | <input type="text">用[type='text'],针对全局唯一的属性可以用这种简略写法 |
标签+属性 | [] | <input type="text">同一个例子,用input[type='text'] |
子元素 | > | <div><input placeholder="Search"></div> 用 div > input[placeholder='Search'] |
不限制层级的子元素 | 空格 | <div><li><a/></li></div>用div a定位。与>对直接子元素定位比较效果,如果用div>a定位不到 |
数组 | :nth-child | <div><li/><li/></div>用 div>li:nth-child(2) |
兄弟元素 | + | <ul><li title="天津市"/><li title="北京市"/>用 ul>li[title='天津市']+li 可以定位到第二个北京市的li |
逻辑与 | [][] | <li role="menuitem" placeholder="Search">用li[role='menuitem'][placeholder='Search'] |
正则 | ^= 开头 $=结尾 *=任意字符 |
<li role="menuitem">可以用li[role^='menu']或者li[role$='item']或者li[role*='enuite']适用于属性值有固定部分+随机值的元素 |
XPath
XPath都是以路径表达式开头,路径分为绝对路径和相对路径,绝对路径以网页的根节点html元素作为起点。以下是定位同一个元素的两种写法,可以直观看到不同
路径分类 | 示例 |
---|---|
绝对路径 | /html/body/div[3]/div/div[2]/div/div[2]/div[2]/div/form/div[2]/div[2]/div/span/div/div/div/div/ul[1]/li[2] |
相对路径 | //li[@title="天津市"] |
以Selector的写法作为参照,XPath的语法如下
分类 | 符号 | 实际的例子 |
---|---|---|
id,class及其他属性 | @ | <span class="h3"> 用//span[@class='h3'] <span placeholder="Search"用//span[@placeholder='Search']> |
属性是否存在 | 只有@没有= | <span business="h3">用//span[@business]查找带有business属性的元素 |
标签通配符 | * | <span class="h3"> 用//*[@class='h3'],可以匹配满足class是h3的所有标签 |
子元素和父元素 | / | <div><input placeholder="Search"></div> 用//div/input |
父元素 | /.. | <div><input placeholder="Search"></div>用//input[@placeholder='Search']/..适用于元素本身特征不明显不方便定位,但是其子元素特征明显的时候 |
不限制层级的子元素 | // | <div><li><a/></li></div>用//div//a定位 |
数组 | [] | <div><li/><li/></div>用 //div/li[2]定位第2个li |
兄弟元素 | 组合使用/和../ | <ul><span title="天津市"/><div/>用 ul>span[title='天津市']/../div 可以定位到第二个div |
逻辑与 | and | <li title="江苏省" role="menuitem">用//li[@title='江苏省' and @role='menuitem'] |
逻辑或 | or | <li title="江苏省" role="menuitem">用//li[@title='江苏省' or @role='enuitem'] |
函数:文本 | text() | <span>保存</span>用 //span[text()='保存'] |
函数:模糊匹配 | contains() | <li class="cascader-menu-item cascader-menu-item-expand">用//li[contains(@class, 'cascader-menu-item')] |
函数:文本开头 | starts-with() | <li title="天津市">用//li[starts-with(@title, '天')] |
函数组合 | <span>保存</span>用 //span[contains(text(), '保')] |
TIPS:定位表达式中可以用单引号,也可以用双引号,但是由于在自动化测试的代码里使用时,双引号会涉及到转义,复制的时候不方便。所以推荐用单引号
其他
除了掌握定位表达式的写法,还可以从流程上进行优化提效,比如与前端同学约定,统一的编码风格、尽量使用唯一性的标签、带业务属性的类名、属性名不要轻易变动等。
网友评论