selenium2.0 - 中文帮助文档

更新时间:2024-03-23 10:00:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

Selenium2.0帮助文档

第1章 Webdirver基础 3

1.1 下载selenium2.0的lib包 3 1.2 用webdriver打开一个浏览器 3 1.3 打开测试页面 3 1.4 GettingStarted 3

第2章 Webdirver对浏览器的支持 5

2.1 HtmlUnit Driver 5 2.2 FireFox Driver 5

2.3 InternetExplorer Driver 5 第3章 使用操作 6

3.1如何找到页面元素 6

3.1.1 By ID 6 3.1.2 By Name 6 3.1.3 By XPATH 6 3.1.4 By Class Name 8 3.1.5 By Link Text 8 3.1.6 By tagName 8 3.1.7 By cssSelector 8

3.2如何对页面元素进行操作 9

3.2.1 输入框(text field or textarea) 9 3.2.2 下拉选择框(Select) 10 3.2.3 单选项(Radio Button) 10 3.2.4 多选项(checkbox) 10 3.2.5 按钮(button) 11 3.2.6 左右选择框 11

3.2.7 弹出对话框(Popup dialogs) 11 3.2.8 表单(Form) 11

3.2.9 上传文件 (Upload File) 11

3.2.10 Windows 和 Frames之间的切换 12 3.2.11 拖拉(Drag andDrop) 12

3.2.12 导航 (Navigationand History) 12 3.3 高级使用 13

3.3.1 改变user agent 13 3.3.2 读取Cookies 13 3.3.3 调用Java Script 14 3.3.4 Webdriver截图 14 3.3.5 页面等待 14

第4章 RemoteWebDriver 18

4.1 使用RemoteWebDriver 18 4.2 SeleniumServer 19

4.3 How to setFirefox profile using RemoteWebDriver

19第5章 封装与重用 19

第6章 在selenium2.0中使用selenium1.0的API 21 第7章 鼠标事件 23

第1章 Webdirver基础

1.1 下载selenium2.0的lib包

http://docs.seleniumhq.org/download/

官方UserGuide:http://seleniumhq.org/docs/

1.2 用webdriver打开一个浏览器

我们常用的浏览器有firefox和IE两种,firefox是selenium支持得比较成熟的浏览器。但是做页面的测试,速度通常很慢,严重影响持续集成的速度,这个时候建议使用HtmlUnit,不过HtmlUnitDirver运行时是看不到界面的,对调试就不方便了。使用哪种浏览器,可以做成配置项,根据需要灵活配置。

打开firefox浏览器:

//Create a newinstance of the Firefox driver WebDriver driver = new FirefoxDriver();

打开IE浏览器

//Create a newinstance of the Internet Explorer driver WebDriver driver = new InternetExplorerDriver ();

打开HtmlUnit浏览器

//Createa new instance of the Internet Explorer driver WebDriverdriver = new HtmlUnitDriver();

1.3 打开测试页面

对页面对测试,首先要打开被测试页面的地址(如:http://www.google.com),web driver 提供的get方法可以打开一个页面: // And now use thedriver to visit Google driver.get(\

1.4 GettingStarted

package org.openqa.selenium.example; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.WebDriverWait; public class Selenium2Example { public static voidmain(String[] args) { // Create a newinstance of the Firefox driver // Notice that theremainder of the code relies on the interface, // not the implementation. WebDriver driver = newFirefoxDriver(); // And now use this tovisit Google driver.get(\// Alternatively thesame thing can be done like this // driver.navigate().to(\ // Find the text inputelement by its name WebElement element =driver.findElement(By.name(\ // Enter something tosearch for element.sendKeys(\ // Now submit the form.WebDriver will find the form for us from the element element.submit(); // Check the title ofthe page System.out.println(\ // Google's search isrendered dynamically with JavaScript. // Wait for the pageto load, timeout after 10 seconds (newWebDriverWait(driver, 10)).until(new ExpectedCondition() { public Booleanapply(WebDriver d) { returnd.getTitle().toLowerCase().startsWith(\} }); // Should see:\ System.out.println(\ //Close the browser driver.quit(); } } 第2章 Webdirver对浏览器的支持

2.1 HtmlUnit Driver

优点:HtmlUnit Driver不会实际打开浏览器,运行速度很快。对于用FireFox等浏览器来做测试的自动化测试用例,运行速度通常很慢,HtmlUnit Driver无疑是可以很好地解决这个问题。

缺点:它对JavaScript的支持不够好,当页面上有复杂JavaScript时,经常会捕获不到页面元素。

使用:WebDriver driver = new HtmlUnitDriver();

2.2 FireFox Driver

优点:FireFox Dirver对页面的自动化测试支持得比较好,很直观地模拟页面的操作,对JavaScript的支持也非常完善,基本上页面上做的所有操作FireFox Driver都可以模拟。

缺点:启动很慢,运行也比较慢,不过,启动之后Webdriver的操作速度虽然不快但还是可以接受的,建议不要频繁启停FireFox Driver。

使用:

WebDriver driver = new FirefoxDriver();

Firefox profile的属性值是可以改变的,比如我们平时使用得非常频繁的改变useragent的功能,可以这样修改:

FirefoxProfile profile = new FirefoxProfile();

profile.setPreference(\WebDriver driver = new FirefoxDriver(profile);

2.3 InternetExplorer Driver

优点:直观地模拟用户的实际操作,对JavaScript提供完善的支持。

缺点:是所有浏览器中运行速度最慢的,并且只能在Windows下运行,对CSS以及XPATH的支持也不够好。

使用:WebDriver driver = new InternetExplorerDriver();

2.4 Chrome Driver

预先下载Chrome驱动,下载地址:http://chromedriver.storage.googleapis.com/index.html 程序通过全路径调用chrome驱动程序。

WebDriver webdriver; String driverLoc =

\;

String driver = \;

System.setProperty(driver, driverLoc); webdriver = new ChromeDriver(); webdriver.get(website);

第3章 使用操作

3.1 如何找到页面元素

Webdriver的findElement方法可以用来找到页面的某个元素,最常用的方法是用id和name查找。下面介绍几种比较常用的方法。

3.1.1 By ID

假设页面写成这样:

那么可以这样找到页面的元素: 通过id查找:

WebElement element = driver.findElement(By.id(\

3.1.2 By Name

通过name查找:

WebElement element = driver.findElement(By.name(\

3.1.3 By XPATH

通过xpath查找:

WebElement element =driver.findElement(By.xpath(\

1)绝对路径

driver.findElement(By.xpath(\如果发生结构改变则找不到

2)相对路径

driver.findElement(By.xpath(\假设在DOM中的第一个 3)使用索引

driver.findElement(By.xpath(\找第二个input元素

4)属性值

driver.findElement(By.xpath(\使用id属性匹配 driver.findElement(By.xpath(\使用alt属性

driver.findElement(By.xpath (\联合多个属性 WebElement previousButton = driver.findElement (By.xpath(\@value='Login']\使用and联合查询

WebElement previousButton = driver.findElement (By.xpath(\@value='Login']\使用or选择查询

5)属性名称

List imagesWithAlt = driver.findElements (By.xpath (\使用属性名称 img中带有alt属性的元素

6)部分属性值

starts-with() driver.findElement(By.XPath(“input[starts-with(@id,’ctrl’)]”)); ends-with() driver.findElement(By.XPath(“input[ends-with(@id,’ctrl’)]”));

contains() starts-with() driver.findElement(By.XPath(“input[contains(@id,’ctrl’)]”)); 7)使用值匹配任意元素属性值

driver.findElement(By.xpath(\任意属性名称为username的元素 8)XPath轴 借住于元素与元素之间的关系定位

ancestor //td[text()=’Product1’]/ancestor::table 选择当前节点所有的父类元素 属性 名称 元素

descendant //table/descendant::td/input 选择当前节点所有子元素

following //td[text()=’Product1’]/following::tr 选择当前元素结束标签后的所有元素 following-sibling //td[text()=’Product1’]/following-sibling::td 当前元素后的兄弟元素 preceding //td[text()=’$150’]/preceding::tr 当前节点开始标签之前的所有节点

preceding-sibling //td[text()=’$150’]/preceding-sibling::td 当前借点之前的所有同级节点

定位单元格元素 方式:

table:定义表格 caption:表格标题 th:表头 tr:行 td:单元 thead:页眉 tbody:主题 tfoot:页脚 col:列的属性 colgroup:列的组

findElement将会查询整个DOM 最终返回第一个找到的匹配的元素 findElement可以查询子类,缩写为

driver.findElement(By.id(\查找一个元素 查找这个元素下的子类top

当findElement找不到元素时。抛出NoSuchElementFoundException findElements()方法返回所有匹配定位策略的WebElement的集合,我们可以使用java中

List类来创建WebElements的实例,实现查找多个元素:

List links = driver.findElements(By.cssSelector(\

3.1.4 By Class Name

假设页面写成这样:

class=\

可以通过这样查找页面元素:

Listcheeses = driver.findElements(By.className(\

3.1.5 By Link Text

假设页面元素写成这样:

WebElement cheese =driver.findElement(By.linkText(\

3.1.6 By tagName

selenium使用findElements遍历tagName为label的元素,定位多个元素将结果存放在List中,然后依次打印出这些元素的文本。

List label=driver.findElements(By.tagName(“label”)); for(WebElement l:label){

System.out.println(l.getText());}

findElement和findElements的区别:

findElement返回一个元素对象,否则抛出异常。

findElements返回符合条件的元素List,如果不存在符合条件的元素就返回一个空的List。

3.1.7 By cssSelector

List cue1=webDriver.findElements(By.cssSelector(\> div >

div.col-md-8 > div > div > h2\

for(WebElement a:cue1){

Assert.assertEquals(\微博数、转发数、评论数按时分布\ System.out.println(a.getText()); }

1)绝对路径 在DOM中的具体位置

findElement(by.cssSelector(“html body div form input”))

或findElement(by.cssSelector(“htmldriver.findElement(By.cssSelector(\第一个input元素。

driver.findElement(By.cssSelector(\标签.class的属性值 3)相对Id选择器

driver.findElement(By.cssSelector(\标签#id driver.findElement(By.cssSelector(\只是#id 4)属性

driver.findElement(By.cssSelector(\使用name属性 driver.findElement(By.cssSelector(\使用alt属性

driver.findElements(By.cssSelector(\通过属性名称查找,页面所有img含有alt属性的标签

driver.findElement(By.cssSelector(\联合多个属性查询

driver.findElements(By.cssSelector(\使用伪类

5)部分属性 (对于页面上有动态变化的属性的元素是非常有用的)

^= driver.findElement(By.cssSelector(Input[id ^ =‘ctrl’]));匹配到id头部 如ctrl_12 $= driver.findElement(By.cssSelector(Input[id ^ =‘ctrl’]));匹配到id尾部 如a_ctrl *= driver.findElement(By.cssSelector(Input[id *=‘ctrl’]));匹配到id中间如1_ctrl_12 高级CSS

1)查询子元素

WebElement userName = driver.findElement(By.cssSelector(\WebElement userName = driver.findEleme(By.cssSelector(\:first-child 定位表单第一个子元素 :last-child 定位表单最后一个子元素 :nth-child(2) 定位表单中第二个子元素 2)使用伪类

driver.findElement(By.cssSelector(\也可使用hover active :enable input:enable 定位属性为enable的input元素 :disable input:disable 定位属性为disable的input元素

:checked input:checked 定位有多选框属性为checked的元素 3)查询兄弟元素

driver.findElement(By.cssSelector(\定位到a 再定位到和它相邻的b

3.2 如何对页面元素进行操作

找到页面元素后,怎样对页面进行操作呢?我们可以根据不同的类型的元素来进行一一说明。

3.2.1 输入框(text field or textarea)

找到输入框元素:

WebElement element = driver.findElement(By.id(\在输入框中输入内容: element.sendKeys(“test”); 将输入框清空: element.clear();

获取输入框的文本内容: element.getText();

3.2.2 下拉选择框(Select)

找到下拉选择框的元素:

Select select = new Select(driver.findElement(By.id(\

选择对应的选择项:

select.selectByVisibleText(“mediaAgencyA”); 或

select.selectByValue(“MA_ID_001”);

不选择对应的选择项: select.deselectAll();

select.deselectByValue(“MA_ID_001”);

select.deselectByVisibleText(“mediaAgencyA”); 或者获取选择项的值:

select.getAllSelectedOptions(); select.getFirstSelectedOption();

3.2.3 单选项(Radio Button)

找到单选框元素:

WebElement bookMode =driver.findElement(By.id(\选择某个单选项: bookMode.click(); 清空某个单选项: bookMode.clear();

判断某个单选项是否已经被选择: bookMode.isSelected();

3.2.4 多选项(checkbox)

多选项的操作和单选的差不多:

WebElement checkbox =driver.findElement(By.id(\checkbox.click();

checkbox.clear();

checkbox.isSelected(); checkbox.isEnabled();

3.2.5 按钮(button)

找到按钮元素:

WebElement saveButton = driver.findElement(By.id(\点击按钮:

saveButton.click(); 判断按钮是否enable:

saveButton.isEnabled ();

3.2.6 左右选择框

也就是左边是可供选择项,选择后移动到右边的框中,反之亦然。例如: Select lang = new Select(driver.findElement(By.id(\lang.selectByVisibleText(“English”);

WebElement addLanguage =driver.findElement(By.id(\addLanguage.click();

3.2.7 弹出对话框(Popup dialogs)

Alert alert = driver.switchTo().alert(); alert.accept(); alert.dismiss(); alert.getText();

3.2.8 表单(Form)

Form中的元素的操作和其它的元素操作一样,对元素操作完成后对表单的提交可以: WebElement approve = driver.findElement(By.id(\approve.click();

或approve.submit();//只适合于表单的提交

3.2.9 上传文件 (Upload File)

上传文件的元素操作:

WebElement adFileUpload = driver.findElement(By.id(\

String filePath = \adFileUpload.sendKeys(filePath);

3.2.10 Windows 和 Frames之间的切换

一般来说,登录后建议是先: driver.switchTo().defaultContent(); 切换到某个frame:

driver.switchTo().frame(\从一个frame切换到另一个frame: driver.switchTo().frame(\切换到某个window:

driver.switchTo().window(\

3.2.11 拖拉(Drag andDrop)

WebElement element =driver.findElement(By.name(\WebElement target = driver.findElement(By.name(\

(new Actions(driver)).dragAndDrop(element, target).perform();

3.2.12 导航 (Navigationand History)

打开一个新的页面:

driver.navigate().to(\

通过历史导航返回原页面: driver.navigate().forward(); driver.navigate().back();

3.2.13 关闭浏览器

在一个自动化测试脚本运行完毕后,我们很可能会采取关闭浏览器的操作,而关闭浏览器的常用操作有如下两种:

driver.close() 方法关闭当前的浏览器窗口。

driver.quit()方法不仅关闭窗口,还会彻底的退出webdriver,,释放与driver server之间的连接。

3.2.14 gettagname应用

获取选择器指定的基于DOM元素的标签名 应用:client.getTagName(selector);

参数:selector,类型为String,元素标签名。 实例

Index.html Lorem ipsum getTagNameAsync.js client.getTagName('#elem').then(function(tagName) { console.log(tagName); // outputs: \ }); getTagNameSync.js it('should demonstrate the getTagName command', function () { var elem = browser.element('#elem'); var tagName = elem.getTagName(); console.log(tagName); // outputs: \ })

3.3 高级使用

3.3.1 改变user agent

User Agent的设置是平时使用得比较多的操作: FirefoxProfile profile = new FirefoxProfile();

profile.addAdditionalPreference(\WebDriver driver = new FirefoxDriver(profile);

3.3.2 读取Cookies

我们经常要对的值进行读取和设置。 增加cookie:

// Now set the cookie. This one's valid for the entire domain Cookie cookie = new Cookie(\driver.manage().addCookie(cookie); 获取cookie的值:

// And now output all the available cookies for the current URL Set allCookies = driver.manage().getCookies(); for (Cookie loadedCookie : allCookies) { System.out.println(String.format(\-> %s\loadedCookie.getValue()));

}

根据某个cookie的name获取cookie的值: driver.manage().getCookieNamed(\删除cookie:

// You can delete cookies in 3 ways // By name

driver.manage().deleteCookieNamed(\// By Cookie

driver.manage().deleteCookie(loadedCookie); // Or all of them

driver.manage().deleteAllCookies();

3.3.3 调用Java Script

Web driver对Java Script的调用是通过JavascriptExecutor来实现的,例如: JavascriptExecutor js = (JavascriptExecutor) driver;

js.executeScript(\inventoryId + \+ fieldName + \

3.3.4 Webdriver截图

如果用webdriver截图是: driver = webdriver.Firefox()

driver.save_screenshot(\

3.3.5 页面等待

因为Load页面需要一段时间,如果页面还没加载完就查找元素,必然是查找不到的。最好的方式,就是设置一个默认等待时间,在查找页面元素的时候如果找不到就等待一段时间再找,直到超时。

Webdriver提供两种方法,一种是显性等待,另一种是隐性等待。 显性等待:

WebDriver driver =new FirefoxDriver();

driver.get(\

WebElement myDynamicElement = (new WebDriverWait(driver, 10)) .until(new ExpectedCondition(){ @Override

public WebElement apply(WebDriver d) {

returnd.findElement(By.id(\}});

隐性等待:

WebDriver driver = new FirefoxDriver();

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get(\

WebElement myDynamicElement =driver.findElement(By.id(\

3.3.6 超时设置

pageLoadTimeout方法用来设置页面完全加载的超时时间,完全加载即页面全部渲染,异步同步脚本都执行完成。前面的文章都是使用get 方法登录安居客网站,大家应该能感觉到每次打开网页后要等很长一段时间才会进行下一步的操作,那是因为没有设置超时时间而get方法默认是等待页面全部加 载完成才会进入下一步骤,加入将超时时间设置为3S就会中断操作抛出异常

import java.util.concurrent.TimeUnit; import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.WebElement;

public class NewTest{

public static void main(String[] args) throws InterruptedException { System.setProperty ( \

\WebDriver driver = new ChromeDriver(); try{

//设置超时时间为3S

driver.manage().timeouts().pageLoadTimeout(3, TimeUnit.SECONDS); driver.get(\

WebElement input=driver.findElement(By.xpath(\input.sendKeys(\

}catch(Exception e){ e.printStackTrace(); }finally{

Thread.sleep(3000); driver.quit(); } }

ps:如果时间参数为负数,效果没有使用这个方法是一样的,接口注释中有相关说明:”If the timeout is negative, page loads can be indefinite”.

如果想在抛出异常后并不中断而是继续执行下面的操作那该怎么办呢?可以使用try,catch的组合来实现这个功能 import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.WebElement;

public class NewTest{

public static void main(String[] args) throws InterruptedException { System.setProperty ( \

\WebDriver driver = new ChromeDriver(); try{

//设置超时时间为3S

driver.manage().timeouts().pageLoadTimeout(3, TimeUnit.SECONDS); driver.get(\}catch(Exception e){

}finally{

WebElement input=driver.findElement(By.xpath(\if(input.isDisplayed())

input.sendKeys(\ } }

这样,当页面加载3S后就会执行下面的操作了。

setScriptTimeout

设置异步脚本的超时时间,用法同pageLoadTimeout一样就不再写了,异步脚本也就是有async属性的JS脚本,可以在页面解析的同时执行

implicitlyWait

识别对象的超时时间,如果在设置的时间类没有找到就抛出一个NoSuchElement异常,用法参数也是和pageLoadTimeout一样,大家可以自己试验试验。

上文中介绍了如何才能在使用pageLoadTimeout抛出异常的同时继续执行,但是现有的方法还是不完美,如果输入框在3S后没有出现还是会 报错,怎么办呢?机智的同学可以想到用sleep方法来实现,为了方便演示换个更明显的需求来说明。安居客的首页上有个切换城市的链接,当点击城市的时候 就会显示全部的城市以供选择这时display属性就会变化 import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; public class NewTest{ public static void main(String[] args) throws InterruptedException { System.setProperty ( \

\WebDriver driver = new ChromeDriver(); try{

//设置超时时间为3S

driver.manage().timeouts().pageLoadTimeout(3, TimeUnit.SECONDS); driver.get(\}catch(Exception e){

}finally{

WebElement city=driver.findElement(By.xpath(\WebElement citys=driver.findElement(By.xpath(\Actions actions=new Actions(driver); actions.clickAndHold(city).perform(); while(citys.isDisplayed()){ System.out.println(\Thread.sleep(3000); }

Thread.sleep(3000); driver.quit(); } }

执行后会每过3S就会输出一次sleep,但是这样的代码显然不够高大上,而且没有限制会一直无限的等待下去,下面介绍一种高大上的方法,就是until,先看代码 iimport org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.WebElement;

import org.openqa.selenium.interactions.Actions;

import org.openqa.selenium.support.ui.WebDriverWait; import org.openqa.selenium.support.ui.ExpectedCondition;

public class NewTest{

public static void main(String[] args) throws InterruptedException { System.setProperty ( \

\WebDriver driver = new ChromeDriver(); try{

//设置超时时间为3S

driver.manage().timeouts().pageLoadTimeout(3, TimeUnit.SECONDS); driver.get(\}catch(Exception e){

}finally{

WebElement city=driver.findElement(By.xpath(\Actions actions=new Actions(driver); actions.clickAndHold(city).perform(); //最多等待10S,每2S检查一次 WebDriverWait wait=new WebDriverWait(driver,10,2000); wait.until(new ExpectedCondition() { public Boolean apply(WebDriver driver) { System.out.println(\return !driver.findElement(By.xpath(\} }); Thread.sleep(3000); driver.quit(); } }

第4章 RemoteWebDriver

当本机上没有浏览器,需要远程调用浏览器进行自动化测试时,需要用到RemoteWebDirver.

4.1 使用RemoteWebDriver

import java.io.File; import java.net.URL; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.openqa.selenium.remote.Augmenter; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.RemoteWebDriver; public class Testing { public void myTest()throws Exception { WebDriver driver = newRemoteWebDriver( new URL(\ DesiredCapabilities.firefox()); driver.get(\ // RemoteWebDriverdoes not implement the TakesScreenshot class // if the driver doeshave the Capabilities to take a screenshot // then Augmenter willadd the TakesScreenshot methods to the instance WebDriveraugmentedDriver = new Augmenter().augment(driver); File screenshot =((TakesScreenshot)augmentedDriver). getScreenshotAs(OutputType.FILE); } } 4.2 SeleniumServer

在使用RemoteDriver时,必须在远程服务器启动一个SeleniumServer: java -jar selenium-server-standalone-2.20.0.jar -port 4446

4.3 How to setFirefox profile using RemoteWebDriver

profile = new FirefoxProfile(); profile.setPreference(\capabilities = DesiredCapabilities.firefox(); capabilities.setCapability(\driver = new RemoteWebDriver(new URL(“http://localhost:4446/wd/hub”),capabilities); driverWait = new WebDriverWait(driver,TestConstant.WAIT_ELEMENT_TO_LOAD); driver.get(\ 第5章 封装与重用

WebDriver对页面的操作,需要找到一个WebElement,然后再对其进行操作,比较繁琐:

// Find the text inputelement by its name

WebElement element = driver.findElement(By.name(\

// Enter something to search for element.sendKeys(\

我们可以考虑对这些基本的操作进行一个封装,简化操作。比如,封装代码: protected void sendKeys(By by, String value){

driver.findElement(by).sendKeys(value); }

那么,在测试用例可以这样简化调用: sendKeys(By.name(\

类似的封装还有:

package com.drutt.mm.end2end.actions; import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.support.ui.WebDriverWait; import com.drutt.mm.end2end.data.TestConstant; public class WebDriverAction { //protected WebDriverdriver; protected RemoteWebDriverdriver; protected WebDriverWaitdriverWait; protected boolean isWebElementExist(By selector) { try { driver.findElement(selector); return true; } catch(NoSuchElementException e) { return false; } } protected StringgetWebText(By by) { try { return driver.findElement(by).getText(); } catch (NoSuchElementException e) { return \ } }

?

一般的修饰键指前面三个。你可以点击下面的 Wiki 链接去了解更多有关修饰键的信息,Modifier key。

回到上面的话题,在 WebDriver 中对于修饰键的使用需要用到 KeyDown(theKey)、keyUp(theKey) 方法来操作。

清单 9. 修饰键方法 KeyDown(theKey)keyUp(theKey)

Actions action = new Actions(driver);action.keyDown(Keys.CONTROL);// 按下 Ctrl 键 action.keyDown(Keys.SHIFT);// 按下 Shift 键 action.keyDown(Key.ALT);// 按下 Alt 键 action.keyUp(Keys.CONTROL);// 释放 Ctrl 键 action.keyUp(Keys.SHIFT);// 释放 Shift 键 action.keyUp(Keys.ALT);// 释放 Alt 键

所以要通过 Alt+F4 来关闭当前的活动窗口,可以通过下面语句来实现:action.keyDown(Keys.ALT).keyDown(Keys.F4).keyUp(Keys.ALT).perform();

而如果是对于像键盘上面的字母键 a,b,c,d... 等的组合使用,可以通过以下语句实现 :action.keyDown(Keys.CONTROL).sednKeys(“a”).perform();

在 WebDriver API 中,KeyDown(Keys theKey)、KeyUp(Keys theKey) 方法的参数只能是修饰键:Keys.SHIFT、Keys.ALT、Keys.CONTROL, 否者将抛出 IllegalArgumentException 异常。 其次对于 action.keyDown(theKey) 方法的调用,如果没有显示的调用 action.keyUp(theKey) 或者 action.sendKeys(Keys.NULL) 来释放的话,这个按键将一直保持按住状态。

回页首

7.4 使用 Robot 类来操作 Keys 没有枚举出来的按键操作

在 WebDriver 中,Keys 枚举出了键盘上大多数的非字母类按键,从 F1 到 F10,NUMPAD0 到 NUMPAD9、ALT\\TAB\\CTRL\\SHIFT 等等,你可以通过以下链接查看 Keys 枚举出来的所有按键,Enum Keys。 但是并没有列出键盘上的所有按键,比如字母键 a、b、c、d ? z,一些符号键比如:‘ {}\\[] ’、‘ \\ ’、‘。’、‘ ? ’、‘:’、‘ + ’、‘ - ’、‘ = ’、、‘“”’,还有一些不常用到的功能键如 PrtSc、ScrLk/NmLk。对于字母键和符号键,前面我们已经提到可以直接使用 sendKeys(“a”),sendKeys(“/”) 的方式来触发这些键盘事件。而对于一些功能组合键,如 Fn + NmLk 来关闭或者打开数字键,或者 Alt+PrtSC 来抓取当前屏幕的活动窗口并保存到图片,通过 WebDriver 的 Keys 是没办法操作的。 这个时候我们就需要用到 Java 的 Robot 类来实现对这类组合键的操作了。

下面就以对 Alt+PrtSc 为例介绍一下 Robot 对键盘的操作。如代码清单 10。

清单 10. 通过 Robot 发出组合键动作

/**** @Description: 这个方法用来模拟发送组合键 Alt + PrtSc, 当组合键盘事件执行之后,屏幕上的活动窗口 * 就被截取并且存储在剪切板了。 接下来就是通过读取剪切板数据转换成 Image 图像对象并保存到本地。 * @param filename : 要保存的图像的名称 */public static void sendComposeKeys(String fileName) throws Exception { // 构建 Robot 对象,用来操作键盘 Robot robot = new Robot(); // 模拟按下键盘动

作,这里通过使用 KeyEvent 类来获取对应键盘(ALT)的虚拟键码

robot.keyPress(java.awt.event.KeyEvent.VK_ALT); // 按下 PrtSC 键 robot.keyPress(java.awt.event.KeyEvent.VK_PRINTSCREEN); // 释放键盘动作,当这个动作完成之后,模拟组合键 Alt + PrtSC 的过程就已经完成,//此时屏幕活动窗口就一被截取并存入到剪切板 robot.keyRelease(java.awt.event.KeyEvent.VK_ALT); //

获取系统剪切板实例 Clipboard sysc = Toolkit.getDefaultToolkit().getSystemClipboard(); // 通过 getContents() 方法就可以将剪切板内容获取并存入 Transferable 对象中 Transferable data = sysc.getContents(null); if (data != null) { /***判断从剪切板获取的对象内容是否为 Java Image 类, 如果是将直接转化为 Image 对象。到此为止,我们就从发出组合键到抓取活动窗口,再读取剪切板并存入 Image 对象的过程就完成了,接下来要做的就是需要将 Image 对象保存到本地。*/ if (data.isDataFlavorSupported(DataFlavor.imageFlavor)) { Image image =

(Image) data .getTransferData(DataFlavor.imageFlavor); writeImageToFile(image, fileName); } } }

Robot 类对键盘的处理是通过 keyPress(int keycode)、keyRelease(int keycode) 方法来实现的,其中他们需要的参数是键盘按键对应的虚拟键码,虚拟键码的值可以通过 KeyEvent 类来获取。在 Java API 中对于虚拟键码的解释如下: 虚拟键码用于报告按下了键盘上的哪个键,而不是一次或多次键击组合生成的字符(如 \是由 shift + \生成的)。 例如,按下 Shift 键会生成 keyCode 为 VK_SHIFT 的 KEY_PRESSED 事件,而按下 'a' 键将生成 keyCode 为 VK_A 的 KEY_PRESSED 事件。释放 'a' 键后,会激发 keyCode 为 VK_A 的 KEY_RELEASED 事件。另外,还会生成一个 keyChar 值为 'A' 的 KEY_TYPED 事件。 按下和释放键盘上的键会导致(依次)生成以下键事件:

KEY_PRESSED

KEY_TYPED(只在可生成有效 Unicode 字符时产生。) KEY_RELEASED

所以当测试中需要用到按下键盘 Alt+PrtSc 键的时候,只需要执行代码清单 10 中两个 keyPress() 和一个 keyRelease() 方法即可。

3.当这两个按键执行结束之后,屏幕上面的活动窗口已经保存到剪切板中。如果需要将其保存本地图片,只需要从剪切板读取并通过 JPEGImageEncoder 类或者 ImageIO 类将其写入本地即可。

清单 11. 使用 JPEGImageEncoder 将 Image 对象保存到本地

/**** @Description: 这个方法用来将 Image 对象保存到本地,主要是通过 JPEGImageEncoder 类来实现图像的 * 保存 * @param image : 要保存的 Image 对象 * @param filename : 保存图片的文件名称 */public static void writeImageToFile(Image image, String fileName) { try { // 获取 Image 对象的宽度和高度, 这里的参数为 null 表示不需要通知任何观察者 int width = image.getWidth(null); int height = image.getHeight(null); BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 通过 BufferedImage 绘制图

像并保存在其对象中 bi.getGraphics().drawImage(image, 0, 0, null); // 构建图像名称及保存路径 String name = Const.DIRECTORY + fileName + Const.FORMAT; File dir = new File(Const.DIRECTORY); if (!dir.exists()) { dir.mkdir(); } FileOutputStream out

= new FileOutputStream(name); @SuppressWarnings(\ JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);encoder.encode(bi); out.flush();out.close(); } catch (Exception e) { e.printStackTrace(); } }

代码清单 11 是通过 JPEGImageEncoder 类将 Image 对象写到本地文件流,注意 Image 对象是在代码清单 10 中的如下语句获取到的:

Clipboard sysc = Toolkit.getDefaultToolkit().getSystemClipboard(); Transferable data = sysc.getContents(null); if (data != null) { if (data.isDataFlavorSupported(DataFlavor.imageFlavor)) { Image image =

(Image) data .getTransferData(DataFlavor.imageFlavor); writeImageToFile(image, fileName); } }

清单 12. 使用 ImageIO 将 Image 对象保存到本地

/**** @Description: 通过使用 ImageIO 类来保存 Image 对象为本地图片 * @param image : 需要保存的 Image 对象 * @param filename : 文件名 */public static void saveImage(Image image, String fileName) throws Exception { // 获取 Image 对象的高度

和宽度 int width = image.getWidth(null); int height = image.getHeight(null); BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g = bi.getGraphics();//通过 BufferedImage 绘

制图像并保存在其对象中 g.drawImage(image, 0, 0, width, height, null); g.dispose(); File f = new File(fileName); // 通过 ImageIO 将图像写入到文件 ImageIO.write(bi, \ }

7.5 使用 sendKeys(keysToSend) 批量上传文件

在 Selenium2.0 之前,要上传文件是比较麻烦的一件事件,因为点击 Upload File 控件会弹出 Windows 窗口以提供用户选择文件,但是 Window 窗口已经是浏览器之外的组件,所以 Selenium 本身没办法控制, 而必须使用 Java Robot 类来模拟键盘去操作剪切板实现上传功能,而且及其不稳定。 在 Selenium 2.0 之后,WebDriver 解决了这个问题。前面已经谈到过,直接使用 WebElement 类的 sendKeys(keysToSend) 方法就可以实现文件上传了。但是如果想批量上传文件,使用 element.sendKeys(“C:\\\\test\\\%upload\\\\test1.txt”, “C:\\\\test\\\%upload\\\\test2.txt”...) 方法也是不行的,它能通过执行,但是实际上没有上传成功。这时可以通过循环的方式来实现文件的批量上传,代码清单 13 是我在百度云上面批量上传文件的测试。

清单 13. 批量上传文件

/**** @Description: 在百度云上测试文件批量上传功能,主要是通过循环的方式去做单一 * 的上传动作 , 登陆过程已经去掉 */@Testpublic void test_mutilUploadFile() throws Exception {System.out.println(\start\ // 获取上传控件元素 WebElement uploadButton = driver.findElement(By.name(\构建上传文件路径,将需要上

传的文件添加到 CharSequence 数组 CharSequence[] files = new CharSequence[5];

files[0] = \ files[1] = \ files[2] =

\ files[3] = \ files[4] = \ // 循环列出每支需要上传的文件路径,做单一上传动作 for(CharSequence file: files){uploadButton.sendKeys(file); } Thread.sleep(2000);System.out.println(\ }

当执行结束后,效果如图 1。

图 1. 批量上传文件

7.6 结束语

在 Selenium WebDriver 中,有了 Actions 类和 Keys 枚举对键盘和鼠标的操作已经做的非常到位,再结合 Java 本身 Robot、KeyEvent 等类的使用,基本上可以满足工作中遇到的对鼠标键盘操作的应用了。

其次要注意的地方是 WebDriver 对浏览器的支持问题,Selenium WebDriver 支持的浏览器非常广泛,从 IE、Firefox、Chrome 到 Safari 等浏览器, WebDriver 都有相对应的实现:InterntExplorerDriver、FirefoxDriver、ChromeDriver、SafariDriver、AndroidDriver、 IPhoneDriver、HtmlUnitDriver 等。根据个人的经验,Firefox 以及 Chrome 浏览器对 WebDriver 的支持最好了,Firefox 搭上 Firebug 以及 Firepath, 在写脚本的过程中非常方便,而 ChromeDriver 是 Google 公司自己支持与维护的项目。HtmlUnitDriver 速度最快,一个纯 Java 实现的浏览器。IE 比较慢,而且对于 Xpath 等支持不是很好。更多关于 Selenium WebDriver 的知识,大家可以从下面的链接去访问 Selenium 官方文档。

第8章 浏览器窗口操作

8.1 Selenium Webdriver java 最大化浏览器窗口。

System.setProperty(\WebDriver driver = new FirefoxDriver(); driver.manage().window().maximize(); 参考文章

http://xebee.xebia.in/2012/04/06/maximize-browser-window-in-selenium-web-driver/

8.2 Selenium Webdriver java 浏览器中 前进,后退,刷新操作。

System.setProperty(\WebDriver driver = new FirefoxDriver(); driver.manage().window().maximize(); driver.get(\driver.navigate().forward(); // 前进 driver.navigate().back(); // 后退 driver.navigate().refresh(); // 刷新 8.3 Webdriver 针对iframe中的元素定位

Selenium2在使用get()方法打开一个网页的时候,是不会继续加载里面的iframe中的内容的(这一点与Selenium有所区别)。那么,我们就需要人为的要求Selenium2对iframe中的内容进行加载。

例子一:

driver.switchTo().frame(driver.findElement(By.xpath(\

例子二:

driver.switchTo().frame(driver.findElement(By.id(\

8.4 切换主页

用getWindowHandle()方法可以快速的进行切换回主页: String strMainHandler = driver.getWindowHandle(); driver.switchTo().window(strMainHandler);

关于iframe中 元素定位和xpath,cssSelector定位可参考: http://blog.csdn.net/dancedan/article/details/7406942

8.5 Webdirver 利用actions 实现 mouseover方法

Actions builder =new Actions(driver);

Actions mousehover=builder.moveToElement(driver.findElement(By.xxx(\mousehover.perform();

红色部分根据实际情况修改。

8.6 webdriver 中 层级定位

参见:http://jarvi.iteye.com/blog/1448025

8.7 webdriver 执行js脚本

http://jarvi.iteye.com/blog/1447755

8.8 webdriver 等待页面加载完成

http://jarvi.iteye.com/blog/1453662

8.9 获取页面对象的属性值

绿色为对象的属性 pk1=wd.findElement(By.xpath(\value\System.out.println(pk1); 8.10 Webdriver 通过调用JavascriptExecutor 使对象隐藏对象出现,操作对象。

http://blog.sina.com.cn/s/blog_539a70d30101ajsg.html

8.11 Selenium webdriver 新跳转页面上找对象解决方法

在执行的测试的时候,需要验证跳转后新的web页面的对象,不是之前页面,用get()跳转后,在新页面找不到对象。

例如:之前是在www.163.com页面操作,现在需要验证下www.sina.com.cn页面上的东西。

解决方法:

WebDriver wd = new FirefoxDriver(); wd.manage().window().maximize(); //当前页面

wd.get(\//跳转新页面

wd.navigate().to(\//如果要回到之前的页面可以用

wd.navigate().to(\或者

wd.navigate().back();

备注: 如果跳转页面都用get()方法,出现的问题就是 在新的页面上没办法查找对象。

第9章 webdriver的断言使用

操作(action)、辅助(accessors)和断言(assertion):

9.1 辅助accessors

这是辅助工具。用于检查应用程序的状态并将结果存储到变量中。

如:storeElementPresent(locator,variableName)

其中参数:locator 表示元素定位器;variableName 用于存储结果的变量名。

即将locator定位到的状态存储到variableName变量中。

如果该元素出现返回true,否则返回false

可同断言一同使用。

断言assertion:

验证应用程序的状态是否同所期望的一致。

常见的断言包括:验证页面内容,如标题是否为X或当前位置是否正确,或是验证该复选框是否被勾选。

9.2 断言被用于三种模式: assert verifywaitfor

Assert 失败时,该测试将终止。

Verify 失败时,该测试将继续执行,并将错误记入日显示屏 。也就是说允许此单个 验证通过。确保应用程序在正确的页面上。

Waitfor用于等待某些条件变为真。可用于AJAX应用程序的测试。

如果该条件为真,他们将立即成功执行。如果该条件不为真,则将失败并暂停测试。直到超过当前所设定的超时时间。 一般跟setTimeout时间一起用

9.3 断言常用的有

assertLocation(判断当前是在正确的页面)、

assertTitle(检查当前页面的title是否正确)、

assertValue(检查input的值, checkbox或radio,有值为”on”无为”off”)、

assertSelected(检查select的下拉菜单中选中是否正确)、

assertSelectedOptions(检查下拉菜单中的选项的是否正确)、

assertText(检查指定元素的文本)、

assertTextPresent(检查在当前给用户显示的页面上是否有出现指定的文本)、

assertTextNotPresent(检查在当前给用户显示的页面上是否没有出现指定的文本)、

assertAttribute(检查当前指定元素的属性的值)、

assertTable(检查table里的某个cell中的值)、

assertEditable(检查指定的input是否可以编辑)、

assertNotEditable(检查指定的input是否不可以编辑)、

assertAlert(检查是否有产生带指定message的alert对话框)、

waitForElementPresent (等待检验某元素的存在。为真时,则执行。)

第10章 定位不到元素问题

10.1 动态id定位不到元素

for example: //WebElement xiexin_element = driver.findElement(By.id(\WebElement xiexin_element = driver.findElement(By.xpath(\,'写 信')]\xiexin_element.click();

上面一段代码注释掉的部分为通过id定位element的,但是此id“_mail_component_82_82”后面的数字会随着你每次登陆而变化,此时就无法通过id准确定位到element。

所以推荐使用xpath的相对路径方法查找到该元素。

10.2 iframe原因定位不到元素

由于需要定位的元素在某一个frame里边,所以有时通过单独的id/name/xpath还是定位不到此元素

比如以下一段xml源文件: