相对于元素较多或较为复杂结构的页面,使用相对路径并多结合轴、在相对路径的定位方法中,我们则需要指定一些关键字和符号来构建路径,以实现准确定位。
标签选择器 —— 选择特定标签类型的元素。需要注意的是,匹配的起始数是1,而不像是下标中的从0开始计算。EX:#id (#表示选择ID)属性选择器 —— 选择具有特定属性的元素。
阅读目录 1. 目的 2. 定位简介 2.1 CSS Selector定位 2.2 XPath定位 2.2.1 相对路径定位 2.2.2 相对路径的运算符运用 2.2.3 轴 2.2.4 函数 3. 注意点 3.1 CSS Selector的使用注意点 3.2 XPath的使用注意点
1. 目的 web自动化测试作为软件自动化测试领域中绕不过去的一个“香饽饽”,通常都会作为广大测试从业者的首选学习对象,相较于C/S架构的自动化来说,B/S有着其无法忽视的诸多优势,从行业发展趋、
【child 轴】
有如下一段代码:
< divclass = " k_interface" > < divclass = " c_app" > < spanclass = " g_center" > test_group_1</ span> </ div> < divclass = " c_app" > < spanclass = " g_center" > test_group_2</ span> </ div> </ div>
如果我们要获取父元素下的第二级div元素下的test_group_2元素,就可以使用child轴。 💎声明:博主日常工作较为繁忙,文章会不定期更新,各类行业或职场问题欢迎大家私信,有空必回。
elements = driver. find_elements( By. XPATH, "count(//div[@class='my-class']) > 1" ) if elements: print ( "元素个数大于 1" ) else : print ( "元素个数小于等于 1" )
判断方法随意,不过在使用count函数时,需要使用find_elements
方法而不是find_element
。
我们上一次介绍了基于配置文件方式的元素管理的方法,接下去博主会就一些元素的高级定位方法来做一个较为全面的讲解。这些高级定位技巧虽然不会在日常的工作中高频出现,但在一些基础定位方法无法见效的场景中却往往会达到意想不到的效果。
contains()
这个函数用来检查元素中的文本内容是否包含指定的字符串。首先 // 是从根节点开始查找,div则是查找下面的所有div元素,然后在所有的div元素中搜索id属性值为ui_automation_t的元素,最后在匹配到的结果中定位下面的所有p元素。
2.2.1 相对路径定位 既然不我们不提倡使用绝对路径来进行XPath方式定位,那么相对路径自然就是其另一面的良好解决方案。
2.1.1 选择器语法 相较于其他的单一定位方式,CSS Selector本身涵盖有以下这些基本语法,这个也是我们后期进行组合定位的重要基础与依据。
driver. find_element( By. XPATH, "//input[contains(@class, 'icon-title')]" )
【与或】 and与or都属于逻辑运算符,可以用于连接多个表达式。标签名、
driver. find_element( By. XPATH, "//p[@class='selected']/self::node()" )
上面的代码使用了self::node()表示当前选择的节点,但它和其他的轴特性不同,一般情况下我们直接使用.
就可以了,没有必要大费周章。EX:parent > child后代选择器 —— 选择某个元素的后代元素。另外就是无论这些span子元素是否直接作为子元素,或者嵌套在更深层次的子元素中,都是可以被后代选择器指定的。而后代选择器是可以指定父元素中的任意子元素的,也就是说这个选择器可以选择div元素下所有具有SignFlow-tab类属性的span子元素。
driver. find_element( By. XPATH, "//div[contains(text(), 'fill')]" )
这里我们使用contains来检查div元素的文本内容是否包含fill。CLASSNAME等常用的元素定位方法往往就会定位不到你想要的元素。")
这里我们直接使用count函数来对元素进行个数判断并返回对应的打印结果。
if driver. find_elements( By. XPATH, "count(//div[@class='advance']) > 1" ) : print ( "找到了符合条件的元素!" ) else : print ( "没有找到符合条件的元素。研发模式特点、driver. find_element( By. XPATH, "//li[@class='selected']/following-sibling::li" )
同样的,//li[@class=‘selected’]不多解释,这里使用following-sibling轴来选择该元素之后的所有同级元素,因为这里选取了之后的所有元素,所以就不需要进行特定的位置条件筛选了,直接指定标签名即可。维护性这三兄弟,所以当普通定位方式失效之后,我们会优先选择CSS Selector,之后才是XPath。
driver. find_element( By. CSS_SELECTOR, "input.Input.i7cW1UcwT6ThdhTakqFm[name=digits]" )
【后代+类】
示例代码如下:
< divclass = " SignFlow-tabs" > < spanclass = " SignFlow-tab" role = " button" tabindex = " 0" > 密码登录</ span> < spanclass = " SignFlow-tab" role = " button" tabindex = " -1" > 短信登录</ span> </ div>
我们使用【后代+类】的组合方式来进行元素定位 这里需要说明一下的是,在html中一个元素被另一个元素所包含,就类似于上面的这段html代码,最外层的div元素是父元素,span元素就是子元素,这个相信应该很好理解。EX:div类选择器 —— 选择具有特定类名的元素。EX:[attribute=value]子选择器 —— 选择某个元素的直接子元素。另外也正是由于其可读性精准度高,在执行测试脚本时其执行速度也是较为快速。EX:.class (.表示选择类)ID选择器 —— 选择具有特定ID的元素。
driver. find_element( By. XPATH, "//input[@name='discount' and @type='content']" )
2.2.3 轴 既然说到了XPath,就绕不过“轴”这个概念,说直白点它就是用来表示当前页面中节点一个大合集,掌握了轴的用法可以帮助我们快速的定位页面中的节点,在复杂的页面中,经常会有多层嵌套的的结构,我们可以跳过一些不相关的节点来直接定位到所需的节点(避免遍历),从而提升脚本的执行效率。属性等来定位元素,同时也正因此特性,该定位方式就具有很高的灵活性与可读性,精准度也较高。
driver. find_element( By. XPATH, "//span[substring(text(), 1, 3) = 'key']" )
以上代码是将span元素进行截取,截取内容为前三个字符,这里的= 'key'
是用来做结果比较的,查看截取的结果是否等于指定的字符内容。内置函数来提升表达式的精简与精准程度,提高代码的可读性;
浏览器内开发者工具中的copy xpath可以看看,但做做参看就行,实用性讲真不高。很多的条件判断都可以用运算符来进行达成。
driver. find_element( By. CSS_SELECTOR, "div.SignFlow-tabs span.SignFlow-tab" )
【子+类】
示例代码如下:
< divclass = " SignFlow-tabs" > < spanclass = " SignFlow-tab" role = " button" tabindex = " 0" > 密码登录</ span> < spanrole = " button" tabindex = " -1" > < spanclass = " SignFlow-tab" > 短信登录</ span> </ span> </ div>
我们使用【子+类】的组合方式来进行元素定位 对于前面介绍的后代选择器来说,子选择器和其的区别在于:子选择器只会选择直接子元素,而后代选择器则可以选择所有子孙元素。那么我该如何用好XPath定位这个最终手段呢?让我们接着往下看。
【标签+类】
比如我们可以组合标签名与类名两个属性,这里我们的HTML代码为:
< divclass = " SignFlow-tab" role = " button" tabindex = " 0" > 登录</ div>
我们使用【标签+类】的组合方式来进行元素定位
driver. find_element( By. CSS_SELECTOR, "div.SignFlow-tab" )
【标签+属性】
举例如下HTML代码:
< linkdata-rh = " true" rel = " apple-touch-icon" href = " https://static.xxx.com/icon-eac.png" sizes = " 60x60" >
我们使用【标签+属性】的组合方式来进行元素定位
driver. find_element( By. CSS_SELECTOR, "link[href]" )
【类+属性】
举例如下HTML代码:
< inputname = " digits" type = " number" class = " Input i7cW1UcwT6ThdhTakqFm" placeholder = " 输入六位短信验证码" value = " " >
我们使用【类+属性】的组合方式来进行元素定位 这里需要注意的是,这个input元素拥有多个属性,这边是查找了三个属性以做到尽量的定位精准为目的,如果只抽取任意两个或多个组合都是可以的。
以下是日常中我们经常会用到的一些路径定位关键字:
. 表示当前节点,即定位的起点 … 表示当前节点的父节点 // 表示从根节点开始查找元素,不考虑当前节点位置 @ 表示元素的属性
光说可能有点抽象,那我们就来看一个对应的例子: 某个HTML的源代码如下:
< html> < head> < title> UI自动化测试平台首页</ title> </ head> < body> < divid = " ui_automation_t" > < h1> 这个是标题1</ h1> < p> 这个是测试信息</ p> </ div> </ body> </ html>
如果我们要定位对应的<p>
标签元素,那我们的XPath相对路径就可以这么写:
// div[ @id = 'ui_automation_t' ] / p
这段相对路径该怎么理解呢?其实很简单,我们结合着上面相对路径的关键字来解读一下。
CSS Selector是通过HTML 元素的 class、
starts-with()
这个函数用来匹配元素的属性值是否以指定的字符串开头。测试工具支持,其整体的完整生态已经远远超过了C/S架构方面的测试价值。但这里有一个地方需要注意的是,轴定位的结果都是一个节点的合集,所以我们定位的时候需要调用find_element方法,而千万不要用find_elements,如果要选择该节点中的所有的节点,我们可以使用ancestor-or-self轴来实现,用法同上,依然调用find_element且用ancestor-or-self关键字来替换掉ancestor即可。
【preceding-sibling 轴】
示例代码如下:
< ul> < li> Beijing</ li> < li> Shanghai</ li> < liclass = " selected" > Guangzhou</ li> < li> Nanjing</ li> < li> Jinan</ li> </ ul>
如果我们想要定位Beijing和Shanghai两个元素,就可以使用以下的路径表达式。
2. 定位简介 上几期中介绍到的常用元素定位方式这里就不在展开篇幅进行赘述了,其实在我们日常的web自动化测试的脚本设计过程中,常常会碰到因为代码规范或开发同学个人的习惯,导致web页面中的元素某些属性值重复或缺失的现象出现,此时再用ID、EX:ancestor descendant
2.1.2 组合定位 当我们掌握了以上这些选择器的全部用法之后,那么在我们设计脚本的过程中运用灵活的组合方式来进行高进度的元素定位。如果比较的结果不匹配,那么这个元素的查找结果仍然会抛出一个NoSuchElementException的异常。
【following-sibling 轴】
还是同样的一套代码:
< ul> < li> Beijing</ li> < li> Shanghai</ li> < liclass = " selected" > Guangzhou</ li> < li> Nanjing</ li> < li> Jinan</ li> </ ul>
假如我们需要选中Nanjing与Jinan这两个元素,就可以使用以下的路径表达式。id、
【descendant 轴】
示例代码如下:
< divclass = " k_interface" > < divclass = " c_app" > < span> test_page</ span> </ div> < divclass = " c_app" > < inputid = " text" placeholder = " Enter your case" > </ div> < divclass = " g_center" > < button> Submit</ button> </ div> </ div>
需要定位k_interface元素的后代元素时,就可以使用descendant轴实现:
driver. find_element( By. XPATH, "//div[@class='k_interface']//descendant::input[@id='text']" )
如果需要查询与其相关的所有后代元素,使用通配符*代替:
driver. find_element( By. XPATH, "//div[@class='k_interface']//descendant::*" )
上面的descendant轴中的后代元素与之前所的子元素区别也是类似的,可以获取到其父节点下所有间接与直接的任意后代元素。
😏作者简介:博主是一位测试管理者,同时也是一名对外企业兼职讲师。相对路径定位的好处就是完全不用考虑结构变化会带来的元素路径变动影响,除非是元素本身发生了变化或是被取消了。
substring()
这个函数用于截取字符串中的指定部分内容。
【self 轴】
实例代码如下:
< divid = " a_word" > < pclass = " selected" > The word is a.</ p> </ div>
这里我们如果要选中p元素,直接使用self轴即可。
driver. find_element( By. XPATH, "//input[@name='discount']" )
【包含】 contains() 函数用于匹配元素的属性值是否包含指定的字符串。作为元素定位的基准来说,我们的选取准则仍然是唯一性、 📡主页地址:【Austin_zhai】 🙆目的与景愿:旨在于能帮助更多的测试行业人员提升软硬技能,分享行业相关最新信息。写法也需要区别开,子选择器使用“>”,而后代选择器使用空格。可读性、
【等于】 很好理解,等于运算符用于匹配元素的属性值是否等于指定的值。运算符、
【parent 轴】
示例代码如下:
< divclass = " k_interface" > < pclass = " c_app" > test_index</ p> </ div>
查找某个元素的父元素,我们就可以使用parent轴来实现:
driver. find_element( By. XPATH, "//p[@class='c_app']/parent::div" )
这里我们通过p元素的class属性c_app来获取其父元素div。下面我们就来介绍一下,一些常用的内置函数。
driver. find_element( By. XPATH, "//li[@class='selected']/preceding-sibling::li[position()<=2]" )
代码中的//li[@class=‘selected’]会选择到Guangzhou这个元素,因为这里指定了class的属性,然后我们使用preceding-sibling轴选择该元素之前的所有同级元素,加之使用了li[position()<=2]的特定条件来筛选出前两个元素。
driver. find_element( By. XPATH, "//div[@class='k_interface']/*[2]/*" )
这里使用child轴来获取后,/*[2]/*
代表的就是第二个div元素下的后代元素test_group_2。
同样的,我们来看看轴相关的一些基础定义:
ancestor 轴 —— 选择当前节点的所有祖先节点descendant 轴 —— 选择当前节点的所有子孙节点parent 轴 —— 选择当前节点的父节点child 轴 —— 选择当前节点的所有子节点preceding-sibling 轴 —— 选择当前节点之前的所有兄弟节点following-sibling 轴 —— 选择当前节点之后的所有兄弟节点self 轴 —— 选择当前节点本身
【ancestor 轴】
例如有下面这样一个HTML代码:
< divclass = " k_interface" > < divclass = " c_app" > < spanclass = " g_center" > </ span> </ div> </ div>
如果我们想要定位span元素的祖先元素(parent)时,就可以使用ancestor 轴实现:
driver. find_element( By. XPATH, "//span[@class='g_center']/ancestor::div[@class='k_interface']" )
上面的这个相对路径表达式用到了ancestor轴,ancestor表示在//span[@class=‘g_center’]的定位结果后使用该轴搜索其节点上的祖先元素,而该祖先的元素指定为div[@class=‘k_interface’]。