selenium元素定位

1.元素定位 javascript

在本章中,咱们将讨论css

          u 使用浏览器工具来检查页面中元素的结构html

          u 使用findElement方法定位元素java

          u 使用findElements方法来定位元素jquery

          u 定位连接web

          u 经过标签名称定位元素ajax

          u 使用CSS选择器定位元素express

          u 使用XPath定位元素api

          u 使用文本定位元素浏览器

          u 使用高级CSS选择器定位元素

          u 使用jQuery选择器

          u 定位表格的行和列

          u 定位表格中的子元素

 

 

1.1.介绍

成功的自动化GUI(图形用户界面)测试取决于从被测试的应用程序中识别和定位GUI元素,而后执行操做和验证这些元素来实现测试流。这能够归结为测试工具备效的识别各类GUI元素的能力。

 

Selenium WebDriver提供一个先进的技术来定位web页面元素。Selenium功能丰富的API提供了多个定位策略如:Name、ID、CSS选择器、XPath等等。咱们也能够执行自定义的定位策略来定位元素。

 

在本章中,咱们将探索如何使用定位策略,从简单的ID,Name和Class开始。

 

在任何一个Web项目中,给GUI的元素附上属性如Name,ID或Class是很是好的作法。这使得应用程序更加容易测试符合易访问性的标准。可是,有时候并非所指望的那样。遇到这些场景,咱们就须要使用高级的定位策略如CSS选择器和XPath。

 

CSS选择器和XPath在Selenium用户中很是流行,可是CSS选择器相比XPath从难易、速度、效率来讲更为推荐你们使用。

1.2.使用浏览器工具来检查页面元素结构

在咱们开始探测定位器以前,咱们须要先分析一下页面和元素,了解一下他们的结构,元素有哪些属性,JavaScript或AJAX是怎么调用的。等等。

 

浏览器为最终用户渲染的视觉元素经过隐藏掉HTML代码和其余资源。当咱们想要用Selenium WebDriver自动的进行交互的时候,咱们须要仔细查浏览器背后渲染页面和元素的代码。咱们须要识别出有用的信息如属性值和元素结构来定位元素,再利用Selenium WebDriver API模拟执行用户的操做。

 

这里有一个BMI体重计算的页面和HTML代码,下图所示

 

 

 

 

 

你能够经过右击浏览器窗口,在弹出的菜单中选择View Page Source来查看页面的代码。代码将会显示在一个独立的窗口中。但这也可能看起来有一点混乱和难以理解。

 

咱们须要一个特别的工具让显示的信息有结构的更易于理解的格式。在这个秘籍中在深刻到定位器以前咱们将会介绍一些这样的工具。

 

如何实现如何实现 

在下面几个部分中,咱们将探讨一些内置在浏览器的工具和插件来分析元素和页面结构。这些工具将帮助咱们了解页面上的元素和它们的属性,DOM结构,JavaScript调用,CSS   样式属性等等。

 

利用Firefox的Firebug插件来检查页面中的元素

新版本的Firefox提供内置的方法来分析页面和元素;然而,咱们将使用Firebug插件具备更强大的功能。你须要从 https://addons.mozilla.org/en-us/firefox/addon/ firebug/   安装Firebug。

 

检查页面的元素,将鼠标移向所需查看的元素后右键鼠标打开弹出菜单。选择Inspect Element with Firebug选项,以下图所示:

 

 

 

HTML代码在Firebug下以树型结构显示出来,以下图所示:

 

 

 

Firebug提供了各类其余调试特性。它还能够为指定元素生成XPath和CSS选择器。为此,选择所需的元素,而后右击鼠标,选择Copy XPathCopy CSS Path选项,以下图所示

 

 

XPath或CSS选择器的值将会复制剪贴板上。

利用Chrome检查页面中的元素

Chrome提供了一个内置的功能来分析页面和元素。这和firebug很类似。你能够将鼠标移向所需查看的元素,右击弹出菜单,而后选择Inspect Element选项。这将在浏览器中打开开发人员工具。显示信息相似于Firebug,以下图所示:

 

 

 

Chrome开发工具还提供一个特性,在那里你能够获得一个元素的XPath,右键单击所需的元素,从弹出菜单中选择Copy XPath

 

利用Internet Explorer检查页面中的元素

相似于Google Chrome,Microsoft Internet Explorer也提供了一个内置的分析页面和元素的特性。

按F12键打开开发人员工具,以下图所示

 

检查一个元素,单击指针()图标,将鼠标悬停在所需查看的元素上。开发工具高亮此元素为蓝色,HTML代码将以树型结构显示,以下图所示:

 

 

 

 

如何实现如何实现 

浏览器开发工具在测试开发的过程中派的上用场。这些工具将帮助你找到定位元素,解析代码,以树结构显示出来。这些工具还提供了样式的应用、页面资源,页面的DOM(文档对象模型),JavaScript代码信息等等。

有些工具还能够运行JavaScript代码进行测试和调试。

在下面的秘籍中咱们将探索Selenium WebDriver的各类定位器 ,这些工具都将帮助你找到和决定使用哪一种Selenium WebDriver API的定位策略和方法。

1.3.使用findElement方法定位元素

selenium WebDriver定位元素是经过使用findElement()和findElements()方法。

findElement()方法返回一个基于指定查寻条件的WebElement对象或是抛出一个没有找到符合条件元素的异常。

 

findElements()方法会返回匹配指定查询条件的WebElements的集合,若是没有找到则返回为空。

 

查询方法会将By实例做为参数传入。Selenium WebDriver提供了By类来支持各类查询策略。

 

下面的表格列出了各类Selenium WebDriver支持的定位策略。

策略

语法

描述

By ID

Java:

driver.findElement(By.id(<element ID>))

经过元素ID属性定位元素

 

C#: driver.FindElement(By.Id(<elementID>))

 

 

Python: 

driver.find_element_by_id(<elementID>)

 

 

Ruby: 

driver.find_element(:id,<elementID>)

 

By Name

Java:

driver.findElement(By.name(<element name>))

经过元素Name属性定位元素

 

C#:

driver.FindElement(By.Name(<element name>))

 

 

Python: 

driver.find_element_by_name(<element name>)

 

 

Ruby: 

driver.find_element(:name,<element name>)

 

 

 

 

By class name

Java:driver.findElement(By.className(<element class>))

经过元素class name属性定位元素

 

C#:

driver.FindElement(By.ClassName(<elementclass>))

 

 

Python: driver.find_element_by_class_name(<elementclass>)

 

 

Ruby: 

driver.find_element(:class,<element class>)

 

By tag name

Java: driver.findElement(By.tagName(<htmltagname>))

经过HTML标记名定位元素

 

C#:  driver.FindElement(By.TagName(<htmltagname>))

 

 

Python: driver.find_element_by_tag_name(<htmltagname>)

 

 

Ruby:

driver.find_element(:tag_name,<htmltagname>

 

By link text

Java: 

driver.findElement(By.linkText(<linktext>))

经过文本定位连接

 

C#:  

driver.FindElement(By.LinkText(<linktext >))

 

 

Python: 

driver.find_element_by_link_text(<linktext >)

 

 

Ruby: 

driver.find_element(:link_text,< linktext >)

 

By partial link text

Java: 

driver.findElement(By.partialLinkText(<linktext>))

经过部分文本定位连接

 

C#: 

driver.FindElement(By.PartialLinkText(<linktext >))

 

 

Python: 

driver.find_element_by_partial_link_text(<linktext >)

 

 

Ruby:

driver.find_element(:partial_link_text,<linktext >)

 

By CSS

Java: 

driver.findElement(By.cssSelector(<css selector>))

经过CSS定位元素

 

C#:  

driver.FindElement(By.CssSelector(<cssselector >))

 

 

 

Python: 

driver.find_elements_by_css_selector (<css selector>)

 

 

Ruby:

driver.find_element(:css,< css selector >)

 

By XPath

Java: 

driver.findElement(By.xpath(<xpath query expression>))

经过XPath定位元素

 

C#:  

driver.FindElement(By.XPath(<xpath query expression>))

 

 

Python: 

driver.find_elements_by_xpath (<xpath query expression>)

 

 

Ruby: 

driver.find_element(:xpath,<xpath query 

expression>)

 

 

在这个秘籍中,咱们将使用findElement()方法来定位元素。

如何实现如何实现 

使用id,name或class属性是定位元素的首选方法。让咱们试试用上面描述的这些方法来定位元素

 

经过ID属性来查找元素

用元素的id是最首选的方法来定位页面元素。W3C的标准中推荐开发人员为每个元素都提供一个独一无二的id属性。拥有id属性,就能够提供一个明确可靠的方法来定位页面上的元素。

当处理DOM的时候,浏览器使用id做为首选识别元素的方法,同时这也是最快速的策略。

如今咱们看看如何在一个登陆表单中使用id属性来定位元素。

<form name="loginForm">

    <label for="username">UserName: </label> <input type="text"  

        id="username" /><br/>

    <label for="password">Password: </label> <input  

        type="password" id="password" /><br/>

    <input name="login" type="submit" value="Login" />

</form>

 

为定位User NamePassword字段,咱们能够经过下面方法使用id属性来定位元素:  

 WebElement username = driver.findElement(By.id("username"));

WebElement password = driver.findElement(By.id("password"));

 

经过Name属性来查找元素

使用元素的id属性来定位是最为推荐的方法,可是你也可能会由于下列缘由不能使用id属性:

          l 不是全部的页面上元素都会指定id属性

          l id属性的值是动态生成的

 

在下面的例子中,登陆表单使用了name属性而不是id属性

 <form name="loginForm">

     <label for="username">UserName: </label> <input type="text"  

         name="username" /><br/>

     <label for="password">Password: </label> <input  

         type="password" name="password" /><br/>

     <input name="login" type="submit" value="Login" />

</form>

咱们可使用经过下面的方法使用name属性来定位元素:

 WebElement username = driver.findElement(By.name("username"));

WebElement password = driver.findElement(By.name("password"));

和id不一样,name属性未必是页面上惟一的属性。你可能会找到多个具备相同name属性的元素,在这样的状况下,页面上的第一个出现的元素将会被选择,可是个元素未必是你想寻找的,这将会致使测试失败。

经过CSS属性来查找元素

除了使用id和name属性,你还可使用class属性来定位元素。class属性是用来指定元素所应用的CSS样式。

在这个例子中,表单元素使用了class属性而不是id属性:

 <form name="loginForm">

     <label for="username">UserName: </label> <input type="text"  

         class="username" /></br>

     <label for="password">Password: </label> <input  

         type="password" class="password" /></br>

     <input name="login" type="submit" value="Login" />

</form>

 

 

 

咱们可使用经过下面的方法使用class属性来定位元素 

WebElement username =  

     driver.findElement(By.className("username"));

WebElement password =  

     driver.findElement(By.className("password")); 

 

如何实现如何实现 

Selenium WebDriver 提供了findElement()方法来定位页面中须要测试的元素。

 

当开始寻找符合指定条件的元素时,它将会查询整个DOM,而后返回第一个找到的匹配的元素。

 

更多说明 更多说明

WebElement类也能够支持查询子类元素。例如,假设页面上有一些重复的元素。可是,他们在不一样的<div>中。咱们第一步能够先定位到其父元素<div>而后在定位其子元素,方法以下:

 WebElement div = driver.findElement(By.id("div1"));

WebElement topLink = div.findElement(By.linkText("top"));

 

你也能够将他们缩写成一行:

 

 WebElement topLink = driver.findElement 

   (By.id("div1")).findElement(By.linkText("top"));

 

NoSuchElementFoundException

findElement()和findElements()方法当找不到相应的元素的时候就会抛出NoSuchElementFoundException异常。

1.4.使用findElements方法定位元素

Selenium WebDriver提供了findElements()方法,能够获得匹配指定规则的集合。当咱们须要在一组类似的元素上操做的时候,这个方法会是很是有用的。例如,咱们能够获得页面上全部的连接或是表格中全部的行等等。

在这个秘籍中,咱们将用findElements()方法获得全部的连接并打印他们的目标超连接。

如何实现如何实现 

测试需求以百度首页为例,咱们要验证百度首页导航连接的数量,并打印出他们的超连接地址

 

package com.example.tests;

import static org.junit.Assert.*;

import java.util.*;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.ie.InternetExplorerDriver;

 

public class Selenium2 {

 @Test

 public void test() {    

     WebDriver driver = new InternetExplorerDriver();

     driver.get("http://www.baidu.com");

     List<WebElement> links = driver.findElements(By.cssSelector("#nv a"));

     //验证连接数量

     assertEquals(10, links.size());

     //打印href属性

     for (int i = 0; i < links.size(); i++) {

   System.out.println(links.get(i).getAttribute("href"));

  }    

  driver.close();

 }

}

 

 

执行后打印的结果为

http://news.baidu.com/

http://tieba.baidu.com/

http://zhidao.baidu.com/

http://music.baidu.com/

http://image.baidu.com/

http://video.baidu.com/

http://map.baidu.com/

http://baike.baidu.com/

http://wenku.baidu.com/

http://www.baidu.com/more/

 

findElements()方法返回全部匹配定位策略的WebElement的集合,咱们可使用java中List类来建立WebElements的实例

 

List类中的size()方法会告诉你这个集合中元素的总数量。

 

经过for循环将获得List中的全部的元素,再调用getAttribute()方法获得元素的属性。

1.5.定位连接

Selenium WebDriver提供了多种定位连接的方法。你能够经过连接的名称和部分名称来定位一个连接。

 

当连接名是动态变化的时候,使用部分匹配就变得很方便。在这个秘籍中,咱们将看如何使用这些方法来定位页面中的连接。

 

如何实现如何实现 

让咱们举个例子来看看如何使用Selenium WebDriver来定位连接。 

经过连接名来定位连接

Selenium  WebDriver的By类中提供了linkTest()方法来定位连接。在下面的例子中,咱们将定位Gmail的连接:

WebElement gmailLink = driver.findElement(By.linkText("GMail"));

assertEquals("http://mail.google.com/",gmailLink.getAttribute("href"));

 

 

经过部分连接名称定位连接

Selenium WebDriver的By类也提供了使用部分连接名来定位连接。当开发人员创建了动态的连接名时这种方法就很是的有用。在这个例子中,有一个连接是用来打开收件箱。这个连接同时也会动态的显示收件箱的数量因此他是在动态变化的过程当中。这里咱们就可使用partiaLinkTest()来定位固定的或已知不变的一部份名称,在这个例子中就是“inbox”。

 

WebElement inboxLink =   

    driver.findElement(By.partialLinkText("Inbox"));

System.out.println(inboxLink.getText());     

 

若是开发人员提供了id,name或是class属性,仍是尽可能使用这些方法来定位。

1.6.使用标签名称定位元素

Selenium WebDriver的By类中提供了tagName()方法来定位HTML标记名称。这和getElementByTagName()很类似。

 

使用标签名称能够很方便地定位元素。例如,定位全部的表格中的<tr>等等。

 

在这个秘籍中,咱们将学习如何使用tagName来定位元素。

 

如何实现如何实现 

咱们假设你的页面中只有一个按钮。你可使用他的标签来定位此按钮,方法以下:

WebElement loginButton = 

driver.findElement(By.tagName("button"));

loginButton.click();

另外一个例子若是你想统计<table>中有多少行,你能够这样来作:

WebElement table = driver.findElement(By.id("summaryTable"));

List<WebElement> rows = table.findElements(By.tagName("tr"));

assertEquals(10, rows.size());

tagName方法查询DOM,而后返回全部匹配条件的元素。当定位单独的一个元素时,这种方法是不可靠的,页面上可能有不少相同的元素。

1.7.使用CSS选择器定位元素 

Cascading Style Sheets ( CSS )是一种样式风格语言用来描述元素的外观和格式。

 

主流的浏览器实现CSS解析引擎使用CSS语法来格式化和样式化页面。CSS的引进是为了让页面信息和样式信息能够分开。更多的CSS信息和CSS选择器请访问 http://en.wikipedia.org/wiki/Cascading_Style_Sheets

 

Selenium WebDriver使用一样的CSS选择器的原则来定位DOM里的元素。这是一个相对XPath更可靠更快速的方式来定位复杂的元素。

 

在这个秘籍中,咱们将探索一些基本的CSS选择器,后面咱们会逐步深刻到更高级的用法。

 

如何实现如何实现 

让咱们探索一些基本的CSS选择器。Selenium WebDriver的By类提供了cssSelector()方法,让咱们可使用CSS选择器来定位元素。

 

使用绝对路径来定位元素

CSS绝对路径指的是在DOM结构中具体的位置。下面一个例,使用绝对路径来定位用户名输入字段。在使用绝对路径的时候,每一个元素之间要有一个空格。

WebElement userName = driver.findElement(By.cssSelector("html body  div div form input"));

你也能够以父子关系的方式”>”来描述这个选择器

WebElement userName = driver.findElement(By.cssSelector("html >  

body > div > div > form > input"));

可是,这个策略会有一些的限制,他取决于页面的整个结构。若是有些许改变,选择器将找不到这个元素。

使用相对路径来定位元素

使用相对路径的时候咱们能够直接定位元素。不用考虑他在DOM中的位置。例如,咱们能够用这样的方法来定位用户输入字段,假设他在DOM中是第一个<input>元素:

WebElement userName = driver.findElement(By.cssSelector("input"));

使用相对路径来定位元素

当咱们使用CSS选择器来查找元素的时候,咱们可使用class属性来定位元素。咱们能够先指定一个HTML的标签,而后加一个“.”符号,跟上class属性的值,方法以下:

WebElement loginButton =  

    driver.findElement(By.cssSelector("input.login"));

这一样能够找到按钮的<input>标签class为login的元素。

你还能够简写查询表达示,只用 .和class属性值,省略掉HTML的标签。可是,这将会返回全部class为login的元素,致使结果并不必定是你所指望的那样。

WebElement loginButton = driver.findElement(By.cssSelector(".login"));

此方法和className()很类似。

使用相对ID选择器来定位元素

咱们也可使用元素的ID来定位。先指定一个HTML标签,而后加上一个“#”符号,跟上id的属性值,以下所示:

WebElement userName =  

driver.findElement(By.cssSelector("input#username"));

这将会返回input标签中id为username的元素。

你能够经过这样来简化一下表达式,输入“#”符号,跟上id的名称便可,省略到HTML的标签。可是,这也将会返回全部id为username的元素,结果未必是你所指望。用的时候要很是当心。

WebElement userName =  

driver.findElement(By.cssSelector("#username"));

这个方法和id选择器策略很像。

使用属性来定位元素

除了class和id属性,CSS选择器也可使用其余的元素属性来定位。下面的例子中,将使用<input>中的Name属性。

WebElement userName =  

driver.findElement(By.cssSelector("input[name=username]"));

使用name属性来定位元素和直接用By类中的name()方法来定位很类似。

让咱们试试使用其余的属性,下面的例子中,命名alt属性来定位<img>元素。

WebElement previousButton =   

driver.findElement(By.cssSelector("img[alt='Previous']"));

你能够会遇到一个属性不足以来定位到一个元素的状况,你须要联合使用其余的属性来达到精确匹配。下面的例子中,使用多个属性来定位<input>元素。

WebElement previousButton = driver.findElement(By.cssSelector("input[type='submit'][value='Login']"));

使用属性名称选择器来定位元素

这个策略和以前的有些不一样,咱们只经过指定元素中属性的名称而不是属性的值来定位元素。例如,咱们想要查找全部<img>标签中,含有alt属性的元素。

List<WebElement> imagesWithAlt =   

driver.findElements(By.cssSelector("img[alt]"));

not()伪类也可使用来匹配不知足规则的元素。例如,想要定位那些<img>标签中不含有alt属性,方法以下:

 List<WebElement> imagesWithoutAlt =  

 driver.findElements(By.cssSelector("img:not([alt])"));

 

部分属性值的匹配

CSS选择器提供了一个部分属性值匹配定位元素的方法。这为了测试那些页面上具备动态变化的属性的元素是很是有用的。例如,在ASP.NET应用中,元素id是动态生成的。下面的表格介绍了如何使用部分匹配的语法:

语法

例子

描述

^=

Input[id^= ' ctrl']

以XXX开始 例如,若是一个元素的ID是ctrl_12,就能够定位到此元素,匹配到id的头部ctrl。

$=

input[id$='_userName']

以XXX结尾 例如,若是一个元素的ID是a_1_userName,这将会匹配到id的尾部_userName。

*=

Input[id*='userName']

包含 例如,若是一个元素的ID是panel_

login_userName_textfield,这将会匹配到此id值的_userName,从而定位到元素。

 

 

CSS选择器是CSS匹配HTML或XML一系元素中的规则中的一个模式和部分。

主流的浏览器都支持对CSS的解析,应用到相应的元素上去。Selenium WebDriver使用CSS解析引擎来定位页面上的元素。CSS选择器提供多样的方法,规则和模式来定位页面上的元素。这也是相对咱们后面说的XPath更加稳定和快速的方法。

使用CSS选择器,能够经过多样的方法来定位元素如Class,ID,属性值和在此秘籍中咱们描述的一些文本内容方法。

1.8.使用XPath定位元素 

XPath是XML路径语言,用来查询XML文档里中的节点。主流的浏览器都支持Xpath,由于HTML页面在DOM中表示为XHTML文档。

Xpath语言是基于XML文档的树结构,并提供了浏览树的能力,经过多样的标准来选择结点。

Selenium WebDriver支持使用Xpath表达式来定位元素。

利用Xpath来定位元素很是方便,可是,便捷的定位策略牺牲了系统的性能。

XPath和CSS中最重要的区别在于,Xpath能够向前和向后查询DOM结构的元素,而CSS只能向前查询。这意味着使用XPath能够经过子元来定位父元素。

在这个秘籍中,咱们将探索一些基本的XPath查询来定位元素而后再学习一些XPath的高级应用。

如何实现如何实现 

让咱们探索一些Selenium WebDriver中基本的XPath表达式。Selenium WebDriver提供了Xpath()方法来定位元素。

 

经过绝对路径定位元素

和CSS绝对路径类似,XPath绝对路径适用于指定元素的位置。这里的一个例子就是使用绝对路径来定位用户名的字段。在每个元素之间须要有一个空格。

WebElement userName =  

 driver.findElement(By.xpath("html/body/div/div/form/input"));

可是,这个策略有局限性,他须要参考整个页面的文档结构。如改变了,此元素的定位将会失败。

经过相对路径定位元素

用相对路径,咱们能够直接找到元素而无论其在DOM中的位置。例如,咱们能够经过以下方法来定位用户名字段,假设这个<input>元素处于DOM中第一个:

WebElement userName = driver.findElement(By.xpath("//input"));

使用索引来定位元素

在前面的示例中,XPath查询将返回第一个DOM中<input>元素。可能会有多个元素都匹配了XPath查询。若是元素不是第一个元素,咱们也能够指定他的个数来找到它。例如在咱们的登陆表单,咱们能够找到密码字段 - 第二个<input>,方法以下:

WebElement passwd = driver.findElement(By.xpath("//input[2]"));

使用XPath及属性值定位元素

和CSS类似,咱们能够在XPath中使用元素的属性来定位元素。在下面的例子中,可使用ID属性来定位用户名字段。

WebElement userName =  

driver.findElement(By.xpath("//input[@id='username']"));

另外一个使用alt属性来定位image属性的例子:

 WebElement previousButton =   

     driver.findElement(By.xpath("img[@alt='Previous']"));

你能够会遇到一个属性不足以来定位到一个元素的状况,你须要联合使用其余的属性来达到精确匹配。下面的例子中,使用多个属性来定位<input>元素。

WebElement previousButton =   

    driver.findElement(By.xpath 

("//input[@type='submit'][@value='Login']"));

 

使用XPath和and操做符也一样能够达到相同的效果

WebElement previousButton = driver.findElement 

(By.xpath("//input[@type='submit'and @value='Login']"));

下面的例子中,使用or操做符任何一个属性知足也将能够对元素进行定位

WebElement previousButton = driver.findElement 

(By.xpath("//input[@type='submit'or @value='Login']"));

使用XPath及属性名称定位元素

这个策略和以前的有些不一样,咱们只经过指定元素中属性的名称而不是属性的值来定位元素。例如,咱们想要查找全部<img>标签中,含有alt属性的元素。

List<WebElement> imagesWithAlt = driver.findElements 

(By.xpath ("img[@alt]"));

 

部分属性值的匹配

相似于CSS选择器,XPath还提供了一种一些方法部分匹配属性来定位元素。这对于网页中的属性是动态变化的时候是很是有用的。例如,ASP.NET应用程序中动态生成id属性值。下面的表说明了使用这些XPath功能:

语法

例子

描述

starts-with()

input[starts-with(@id,'ctrl')]

例如,若是元素的ID为ctrl_12,将会匹配以ctrl开始的属性值。

ends-with()

input[ends-with(@id,'_userName')]

例如,若是元素的ID为a_1_userName,将会匹配以userName结尾的属性值。

contains()

Input[contains(@id,'userName')]

例如,若是元素的ID为panel_login_userName_textfield,将会匹配含有userName属性值。

 

 

使用值来匹配任意属性及元素

XPath能够匹配任意元素属性中指定的值。例如,在下面的XPath查询中,“userName”是指定的。XPath将会检查全部元素中是否有属性等于”userName”,并将其返回。

 

WebElement userName =  

driver.findElement(By.xpath("//input[@*='username']"));

 

使用XPath轴来定位元素

XPath轴是借助于文档中元素与元素之间的关系来定位。下面有一个简单的<table>的XPath轴的例子。

 

下面是用图形来表示HTML元素间的关系

 

 

描述

例子

结果

ancestor

选择当前节结点全部的父类元素,包括祖先元素

//td[text()='Product 1']/ancestor::table

获得table元素

descendant

选择当前节点全部子元素

//table/

descendant::td/input

获得第三例第二行的input元素

following

选择当前元素结束标签后的全部元素

//td[text()='Product 

1']/following::tr

获得第到第二行的tr元素

following-

sibling

选择当前元素后的兄弟元素

//td[text()='Product 

1']/following-

sibling::td

获得第二行第二列的td元素

preceding

选取文档中当前节点的开始标签以前的全部节点

//td[text()='$150']/

preceding::tr

获得第一行tr

preceding-

sibling

选取当前节点以前的全部同级节点。

//td[text()='$150']/

preceding-sibling::td

获得第三行第一列的td

 

 

更多关于XPath轴请访问http://www.w3schools.com/xpath/xpath_axes.asp 。 

Xpath是处理、查询浏览器DOM强大的语言,能够浏览DOM中的元素和属性。XPath也提供了一些规则、函数和语法来定位元素。

 

主流的浏览器都支持XPath,Selenium WebDriver也提供了经过XPath来定位元素的能力。

 

使用By类中的Xpath()方法能够定位元素。XPath的查询是慢于CSS选择器,由于XPath支持双向的查询。你能够经过元素的父,兄弟,子节点来定位元素。

1.9.使用文本元素 

当你测试网页应用的时候,你也可能遇到开发人员没有分配任何属性给元素,这时候定位元素就会变得很困难。

 

使用CSS选择器或XPath,咱们可使用他的本文内容来定位元素。在这个秘籍中,咱们将探索如何使用文本值来定位元素。

如何实现如何实现 

使用文原本定位元素,CSS选择器和XPath提供了方法来经过文本定位元素。若是一个元素包含一个指定的文本,将会返回到测试。

 

使用CSS选择器伪类定位元素

CSS选择器提供了contains()伪类来经过指定文本定位元素。例如,你能够经过表格里的内容来定位单元格,方法以下:

WebElement cell =   

driver.findElement(By.cssSelector("td:contains('Item 1')"));

contains()伪类接受一个被查询的文本做为参数。而后查询全部<td>标签里包含指定文本的元素。(注:contains()方法已经被CSS3弃用了)

 

以百度首页为例,如今我想定位新闻连接

WebElement news = 

driver.findElement(By.cssSelector("a:contains('新')"));

做为contains()的替代,你可使用innerText属性(不支持Firefox)或textContent属性(支持Firefox),方法以下:

WebElement news =   

driver.findElement(By.cssSelector("a[innerText='新闻']"));

 

WebElement news = driver.findElement

(By.cssSelector("a[textContent='新闻']"));

 

使用XPath的text函数

XPath提供了text()方法来定位指定文本的元素,方法以下:

WebElement cell = driver.findElement 

(By.xpath("//td[contains(text(),'Item 1')]"));

 

这里contains()与text()函数一块儿使用。text()函数,返回完整的文本,contains()函数将检查是否包含此文本。

 

使用XPath精确文本定位元素

利用XPath,经过精确的文原本定位元素,方法以下:

WebElement cell = driver.findElement 

    (By.xpath("//td[.='Item 1']"));

CSS选择器和XPath提供基于元素文本内容方法来定位元素。这种当元素没有足够的属性或当没有其余策略时会很方便找到这些元素。

 

对于使用文本定位,不管是CSS选择器仍是XPath都是搜索整个DOM,返回匹配的元素。

1.10.使用高级的CSS选择器定位元素 

咱们在以前学习了一些基本的CSS选择器,在此秘籍中,咱们将探索用一些高级的CSS选择器来定位元素

如何实现如何实现 

在1.7章节中,咱们已经探索了一些基本的CSS选择器,让咱们探索一些高级的CSS选择器,如相邻的兄弟结合伪类的使用。

查询子元素

CSS选择器提供了多种方法经过父元素来定位它的子元素。仍是以前的例子

 <form name="loginForm">

     <label for="username">UserName: </label> <input type="text"  

         class="username" /></br>

     <label for="password">Password: </label> <input  

         type="password" class="password" /></br>

     <input name="login" type="submit" value="Login" />

</form>

 

 

若是想定位表单中的用户名输入框,咱们使用在其父子元素间使用“>”符号。

WebElement userName =  driver.findElement

(By.cssSelector("form#loginForm > input"));

类似的使用nth-child()方法也能够定位成功,方法以下:

WebElement userName = driver.findElement 

    (By.cssSelector("form#loginForm :nth-child(2)"));

下列表格列出了使用伪类来定位子元素的例子:

伪类

例子

描述

:first-child

form#loginForm :first-child

定位表单里第一个子元素username标签

:last-child

form#loginForm :last-child

定位表单最后一个子元素Login按钮

:nth-child(2)

form#loginForm :nth-child(2)

定位表单中第二个子元素username的输入框

 

 

查询兄弟元素

 

利用CSS选择器,咱们可使用“+”操做符来定位兄弟元素。仍是以百度首页为例

,可使用下例方法来定位百度导航中的“网页”超连接

WebElement web =  

driver.findElement(By.cssSelector("#nv a + b"));

#nv a定位到“新闻”连接,“+ b“后就找到其兄弟<b>元素

使用用户操做伪类

使用用户的操做行为:focus伪类,定位焦点在input框中的元素,方法以下:

WebElement productDescription =  

    driver.findElement(By.cssSelector("input:focus"));

你也可使:hover和:active伪类来定位元素

使用UI状态伪类

使用UI状态伪类,咱们能够经过元素的各类状态来定位,如enabled,disable,checked。 下例表格给予了详细的说明

 

伪类

例子

描述

:enabled

input:enabled

定位全部属性为enable的input的元素

:disabled

input:disabled

定位全部属性为disabled的input的元素

:checked

input:checked

定位全部多选框属性为checked的元素

 

 访问 http://www.w3schools.com/cssref/css_selectors.asp 查询更多CSS选择器的用法

1.11.使用jQuery选择器

jQuery选择器是jQuery库中很是重要的功能。jQuery选择器是基于CSS1-3选择器,加上一些额外的选择器。这些选择器和CSS选择器的使用方法很类似,容许开发人员简单快速的识别页面上的元素。一样能够定位HTML中的元素做为一个单独的元素或是一个元素集合。

jQuery选择器可使用在那些不支持CSS选择器的浏览器上。

在这个秘籍中,咱们将简单的探索如何在Selenium WebDriver中使用jQuery选择器

如何实现如何实现 

 

以jQuery官网为例,网站自己已经自动加载了jQuery的库,因此咱们能够在脚本中直接使用jQuery语法。下面的例子中咱们想使用jQuery的选择器:even选出右侧导航栏中偶数(第一位是索引是0)超连接DownloadBlog、Browser Support

package com.example.tests;

import static org.junit.Assert.*;

import java.util.*;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.ie.InternetExplorerDriver;

public class Selenium2 {

 WebDriver driver = new InternetExplorerDriver();

 JavascriptExecutor jse = (JavascriptExecutor)driver;

 @Test

 public void jQueryTest() { 

     driver.get("http://www.jquery.com/");

 

       List<WebElement> elements = 

         (List<WebElement>)jse.executeScript

         ("return jQuery.find" +

         "('.menu-item a:even')");  

       assertEquals(3,elements.size());

   assertEquals("Download",elements.get(0).getText());   

   assertEquals("Blog",elements.get(1).getText()); 

   assertEquals("Browser Support",elements.get(2).getText()); 

      driver.close();

 }

}

 

 

Selenium WebDriver使用jQuery API加强了jQuery选择器,可是,咱们须要确认页面以经加载了jQuery。jQuery API提供了find()方法来查询元素。咱们须要使用JavaScriptExecutor类来执行jQuery的find()方法。

 

find()方法返回了符合查询条件的元素集合。更多jQuery选择器信息请查询 http://api.jquery.com/category/selectors/

 

在使用jQuery选择器的时候,有的页面并未加载jQuery库,这时候你能够在加载页面的时候注入jQuery库,方法以下:

private void injectjQueryIfNeeded() {

    if (!jQueryLoaded())

        injectjQuery();

}

public Boolean jQueryLoaded() {

    Boolean loaded;

    try {

        loaded = (Boolean) driver.executeScript("return  

            jQuery()!=null");

    } catch (WebDriverException e) {

        loaded = false;

    }

    return loaded;

}

public void injectjQuery() {

 //在head中拼出加载jquery的html

    driver.executeScript(" var headID =  

        document.getElementsByTagName(\"head\")[0];"

    + "var newScript = document.createElement('script');"

    + "newScript.type = 'text/javascript';"

    + "newScript.src = 'http://ajax.googleapis.com/ 

        ajax/libs/jquery/1.7.2/jquery.min.js';"

    + "headID.appendChild(newScript);");

}

 

 

 

仍是以百度首页为例,百度首页没有jQuery库。咱们想定位百度导航栏上面的全部超连接元素,并输出结果。

package com.example.tests;

import static org.junit.Assert.*;

import java.util.*;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.ie.InternetExplorerDriver;

public class Selenium2 {

 WebDriver driver = new InternetExplorerDriver();

 JavascriptExecutor jse = (JavascriptExecutor)driver;

 @Test

 public void jQueryTest() {  

     driver.get("http://www.baidu.com/");

     injectjQueryIfNeeded();

      List<WebElement> elements = 

       (List<WebElement>)jse.executeScript

       ("return jQuery.find('#nv a')");

      assertEquals(7,elements.size()); //验证超连接的数量

       for (int i = 0; i < elements.size(); i++) {

    System.out.print(elements.get(i).getText() + "、");

   }    

         driver.close();

 }

 

 private void injectjQueryIfNeeded() {

     if (!jQueryLoaded())

         injectjQuery();

 }

 //判断是已加载jQuery

 public Boolean jQueryLoaded() {

     Boolean loaded;

     try {

         loaded = (Boolean)jse.executeScript("return " +

 

           "jQuery()!=null");

     } catch (WebDriverException e) {

         loaded = false;

     }

     return loaded;

 }

 //经过注入jQuery

 public void injectjQuery() {

  jse.executeScript(" var headID = " 

  +"document.getElementsByTagName(\"head\")[0];"

     + "var newScript = document.createElement('script');"

     + "newScript.type = 'text/javascript';"

     + "newScript.src = " 

     +"'http://ajax.googleapis.com/ajax/"

     +"libs/jquery/1.7.2/jquery.min.js';"

     + "headID.appendChild(newScript);");

  }  

}

 

 

injectjQueryIfNeeded()方法首先经过jQueryLoaded()方法来判断网页中是否加有jQuery对象。若是没有,再调用injectjQuery()方法经过增长一个<Script>元素来实时加载jQuery库,参考的是Google在线库,你能够修改例子中的版本,使用最新的jQuery版本。

 

1.12.定位表格行和单元格

在处理表格时,咱们能够经过By类中的一些方法快速有效的来定位表格的行和单元格。

在这个秘籍中,咱们将学习如何定位表格中的行和列。

如何实现如何实现 

让咱们建立一个简单的测试来打印表格中的数据,经过下面的方法来定位表格的行和列:

以W3C School的网页为例 http://www.w3school.com.cn/html/html_tables.asp   咱们的需求是先判断一下这个表格是多少行,而后才将每个单元格的数据打印出来。

 

 

 

package com.example.tests;

import static org.junit.Assert.*;

import java.util.*;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.ie.InternetExplorerDriver;

public class Selenium2 {

 WebDriver driver = new InternetExplorerDriver();

 JavascriptExecutor jse = (JavascriptExecutor)driver;

 @Test

 public void tableTest() {  

     driver.get

     ("http://www.w3school.com.cn/html/html_tables.asp");   

     //首先获得全部tr的集合

     List<WebElement> rows = 

       driver.findElements(By.cssSelector(".dataintable tr")); 

        //验证表格的行数

     assertEquals(11,rows.size());

         //打印出全部单元格的数据

     for (WebElement row : rows) { 

      //获得当前tr里td的集合

         List<WebElement> cols =  

           row.findElements(By.tagName("td")); 

         for (WebElement col : cols) {

          System.out.print(col.getText());//获得td里的文本

         }

         System.out.println();

     }

        driver.close();

 }

 

}

 

 

1.13.定位表格中的子元素

对于简单的表格处理还相对容易些。可是,你可能会遇到相对复杂的表格,表格单元格中还有子元素要和用户进行交互。例如,在一个电子商务网的购物车页面,表格中内嵌了不少复杂的元素。

 

 

此外,这些元素是基于用户操做动态生成的。定位这些元素是一个比较有挑战的任何。

 

在此秘籍中,咱们将探索使用CSS和XPath定位表格的子元素。

如何实现如何实现 

这里有一个表格的例子,列出了系统用户和各自的权限。咱们要建立一个测试选择相应的多选框并检查选择的东西是否授予给了用户。

 

数据中每一行代码以下:

<tr>

    <td>Nash</td>

    <td><a href="mailto:nash@test.com">Nash@test.com</a></td>

    <td>

        <div>

            <label for="user128_admin">Admin</label>

            <input type="checkbox" id="user128_admin"  

                checked="true"/>

            <label for="user128_cm">Content Manager</label>

            <input type="checkbox" id="user128_cm"/>

            <label for="user128_browser">Browser</label>

            <input type="checkbox" id="user128_browser"/>

        </div>

    </td>

</tr>

多选框中的ID是动态的不能和用户关联,可是咱们处理这样的问题可使用CSS选择器和XPath。在这个例子中,咱们想要给nash用户授予admin的权限。这可能经过CSS选择器来实现,方法以下:

WebElement adminCheckBox = driver.findElement 

    (By.cssSelector("td:contains('Nash')+td+td>div>label:contains  

    ('Admin')+input"));

adminCheckBox.click();

咱们也可使用XPath来实现:

WebElement adminCheckBox = driver.findElement 

    (By.xpath("//td[contains(text(),'Nash')]/following- 

    sibling::td/descendant::div/label 

    [contains(text(),'Admin')]/following-sibling::input"));

adminCheckBox.click();

父,子,兄弟元素,使用CSS或是XPath方法将对于关联用户设计出通用的定位策略有很是大的帮助。简言之,这个策略就是基于元素与元素之间的关系进行定位。

回到咱们的问题,首先咱们须要找到一个惟一方法来识别表中的用户。为此,咱们可使用单元格中的用户名来定位,方法以下:

CSS

XPath

td:contains('Nash')

//td[contains(text(),'Nash')]

 

 

下一步,咱们须要找到子元素的单元格,对于用户名来讲是后面的第2个单元格

CSS

XPath

td:contains('Nash')+td+td

//td[contains(text(),'Nash')]/

following-sibling::td/descendant::div

 

 

下一步,就要定位到正确的多选框

CSS

XPath

td:contains('Nash')+td+td>div>label:contains('Admin')+input

//td[contains(text(),'Nash')]/

following-sibling::td/descendant::div/label[contains(text(),'Admin')]/following-sibling::input

相关文章
相关标签/搜索