Selenium自动化一般需要几个步骤操作:定位元素,获取元素,操作元素,获取返回结果,断言(返回结果与期望结果是否一致),最后自动化出测试报告。
一、WebDriver API提供了8种元素定位的方法
1、id
2、name
3、class name
4、link text
5、Xpath
6、Css selector
7、tag name
8、partial link text
-
定位Web页面上的元素可以通过元素区别于其他元素的一些属性:id,name,class name,tag name等;
-
可以通过位置属性:XPath和CSS,提供了以标签名为层级关系的定位方式;
-
XPath和CSS同样提供了通过相关元素来查找最终元素的方式;
import org.openqa.selenium.By;
...
findElement(By.id()) //方法通过 id 属性定位来元素
findElement(By.name()) //通过 name 属性来定位元素
findElement(By.className()) //通过 class 属性来定位元素
findElement(By.tagName()) //通过元素的 tag name 来定位元素
findElement(By.linkText()) //法通过元素标签对之间的文本信息来定位元素
findElement(By.partialLinkText()) //通过元素标签对之间的部分文本信息来定位元素
findElement(By.xpath()) //使用 XPath 语言来定位元素
findElement(By.cssSelector()) //用于 CSS 语言定位元素
(一)Id定位
HTML规定id属性在HTML文档中必须唯一,WebDriver提供的id定位方法就是通过元素id属性查找元素
通过id定位百度输入框与百度搜索按钮,如下
driver.findElement(By.id("kw")).sendKeys("XXX");
driver.findElement(By.id("su")).click();
(二)Name定位
HTML规定name来指定元素的名称,name的属性值,在当前页面可以不唯一。
通过name定位百度输入框
driver.findElement(By.name("wd")).sendKeys("XXX");
(三)class定位
HTML规定class来指定元素的类名,用法和id,name类型
通过class属性定位百度输入框和搜索按钮
driver.findElement(By.className("s_ipt")).sendKeys("XXX");
driver.findElement(By.className("bg s_btn")).click();
(四)tag定位
HTML的本质就是通过tag来定义实现不同的功能,每一个元素本质上也是一个tag。因为一个tag往往用来定义一类功能,所以通过tag识别某个元素的概率很低。例如我们打开任意一个页面,查看前端都会发现大量的div、input、a等tag,所以很难通过tag name去区分不同的元素
通过标tag name定位百度的输入框与百度按钮会发现他们完全相同
driver.findElement(By.tagName("input")).sendKeys("XXX");
(五)link定位
link定位是专门用来定位文本连接,获取百度首页的文本连接
findElement(By.linkText("新闻")).click();
(六)partial link定位
partial link定位是对link定位的一种补充,有些文本链接会比较长,这个时候就可以取文本的一部分定位,只要这一部分信息可以唯一的标识这个链接。
<a class="mnav" name="tj_lang" href="#">一个很长很长的文本链接</a>
通过partial link 定位如下
findElement(By.partialLinkText("一个很长的"))
findElement(By.partialLinkText("文本链接"))
(七)CSS定位
CSS(Cascading Style Sheets)是一种语言,他被用来描述HTML和XML文档的表现。CSS使用选择器来为页面元素绑定属性。这些选择器可被Selenium用作另外的定位策略。CSS可较为灵活地选择控制任意属性,一般情况下定位速度要比xpath快;
下面以百度输入框和搜索按钮为例介绍 CSS 定位的用法:
<span class="bg s_ipt_wr">
<input id="kw" class="s_ipt" autocomplete="off" maxlength="100" value="" name="wd">
</span>
<span class="bg s_btn_wr">
<input id="su" class="bg s_btn" type="submit" value="百度一下">
</span>
//1、通过 class 属性定位, 点号(.)表示通过 class 属性来定位元素;
findElement(By.cssSelector(".s_ipt"))
findElement(By.cssSelector(".bg s_btn"))
//2、通过 id 属性定位, 井号(#)表示通过 id 属性来定位元素;
findElement(By.cssSelector("#kw"))
findElement(By.cssSelector("#su"))
//3、通过标签名定位, 在 CSS 语言中,用标签名定位元素不需要任何符号标识,直接使用标签名即可;
findElement(By.cssSelector("input"))
//4、通过父子关系定位, 有标签名为span的父亲元素,查找它的所有标签名叫 input 的子元素;
findElement(By.cssSelector("span > input"))
//5、通过属性定位, 在CSS中也可以使用元素的任意可以唯一标识这个元素的属性。对于属性值来说,可加引号,也可不加,但注意和整个字符串的引号进行区分;
findElement(By.cssSelector("input[autocomplete='off']"))
findElement(By.cssSelector("input[maxlength='100']"))
findElement(By.cssSelector("input[type='submit']"))
//6、组合定位, 把上面的定位策略组合起来使用
findElement(By.cssSelector("form.fm>span>input.s_ipt"))
findElement(By.cssSelector("form#form>span>input#su"))
XPath 与 CSS 的类似功能的简单对比
(八)XPath定位
XPath是一种在XML文档中定位元素的语言,有多重定位策略。因为HTML可以看做XML的一种实现,所以Selenium用户可以使用这种强大的语言在Web应用中定位元素
1、绝对路径定位
如果把一个元素看做一个人的话,假设这个人没有任何属性特征(姓名,身份证号),但这个人存在于某个地理位置,如xx省xx市xx区xx路xx号。对于页面上的元素而言也会有这样的一个绝对地址
通过绝对路径的方式找到百度输入框和搜索按钮
findElement(By.xpath("/html/body/div/div[2]/div/div/div/from/span/input"))
findElement(By.xpath("/html/body/div/div[2]/div/div/div/from/span[2]/input"))
XPath 主要用标签名的层级关系来定位元素的绝对路径,**最外层为 html 语言,有 body 文本内,一级一级往下查找,如果一个层级下有多个相同的标签名,那么就按上下顺序确定是第几个,例如 div[2]表示当前层级下的第二个 div 标签
2、元素属性定位
除了使用绝对路径外,XPath 也可以使用元素的属性值来定位。
以百度输入框和搜索按钮为例
// // 表示当前页面某个目录下;
// input 表示定位元素的标签名;
// [@id='kw'] 表示这个元素的 id 属性值等于 kw;
findElement(By.xpath("//input[@id='kw']")) //通过id属性值来定位
findElement(By.xpath("//input[@id='su']"))
findElement(By.xpath("//input[@name='wd']")) //通过name属性值来定位
findElement(By.xpath("//input[@class='s_ipt']")) //通过class属性值来定位
findElement(By.xpath("//*[@class='bg s_btn']")) //如果不想指定标签名,则也可以用星号(*)代替
//使用 XPath 不局限于 id、name 和 class 这三个属性值,元素的任意属性值都可以使用,只要它能唯一的标识一个元素
findElement(By.xpath("//input[@maxlength='100']")) //通过maxlength属性值来定位
findElement(By.xpath("//input[@autocomplete='off']"))
findElement(By.xpath("//input[@type='submit']"))
3、层级与属性结合
如果一个元素本身并没有可以唯一标识这个元素的属性值,那么我们可以找其上一级元素,如果它的上一级元素有可以唯一标识属性的值,也可以拿来使用
//baidu.html 文本
<form id="form" class="fm" action="/s" name="f">
<span class="bg s_ipt_wr">
<input id="kw" class="s_ipt" autocomplete="off" maxlength="100" value="" name="wd">
</span>
</form>
百度输入框本身没有可利用的属性值,那么我们可以查找它的上一级属性;如果父元素没有可利用的属性值,那么可以继续向上查找“爷爷”元素。通过 XPath 描述如下
findElement(By.xpath("//span[@class='bg s_ipt_wr']/input"))
//span[@class='bg s_ipt_wr'] 通过 class 属性定位到父元素,后面/input 就表示父元素下面的子元素
findElement(By.xpath("//form[@id='form']/span/input")) //通过爷爷元素form查找input
findElement(By.xpath("//form[@id='form']/span[2]/input"))
4、使用逻辑运算符
如果一个属性不能唯一地区分一个元素,我们还可以使用逻辑运算符连接多个属性来查找元素
//baidu.html 文本
<input id="kw" class="su" name="ie">
<input id="kw" class="aa" name="ie">
<input id="bb" class="su" name="ie">
如上面的三行元素,假设我们现在要定位第一行元素,如果使用 id 将会与第二行元素重名,如果使用 class将会与第三行元素重名。如果同时使用 id 和 class 就会唯一的标识这个元素,那么这个时候就可以通过逻辑运算符“and”来连接两个条件;也可以用“and”连接更多的属性来唯一地标识一个元素;
findElement(By.xpath("//input[@id='kw' and @class='su']/span/input"))
二、总结
最后总结一下关于xpath定位的一些想法
1、全路径定位: //html/body/div/div/div[2]/p[3]/a(用得少)
2、半路径定位: //div[2]/p[3]/a(用得少)
3、字符定位: //div/ul/li[text()="百科"]
4、包含字符定位: //div/p/a[contains(text(),"百")]
5、超链接定位: link=百科
6、相对位置定位: //div/p[a="文库"]/a
7、属性定位: //div/p/a[@name="tj_baike"]
8、使用包含属性定位://div/input[contains(@class,"btn")]