【javawb】处理windows的进程

Selenium WebDriver java提供了windowsUtils类来和Windows操作系统交互。在测试开始时,我们需要关掉已经一些进程。

如下例子,关闭已打开的火狐浏览器:

@Before

public void setUp()

{

WindowsUtils.tryToKillByName("firefox.exe");

driver = new FirefoxDriver();

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

driver.manage().window().maximize();

}

我们可以使用tryToKillByName方法来关闭任何的windows的进程。如果这个进程不存在则会抛出一个异常,但是,测试还是会正常的执行下去。

 

u 通过WebDriver读取windows注册表中的值

WindowsUtils类提供了多种方法和windows操作系统的注册表进行交互,如果测试是运行在windows操作系统上的IE浏览器,则可能需要修改一些IE注册表里的设置。使用WindowsUtils类就可以很方便的解决。

 

我们需要导入org.openqa.selenium.os.WindowsUtils类然后使用readStringRegistryValue()方法来读取注册表里的键值。package com.example.tests;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.ie.InternetExplorerDriver;

import org.openqa.selenium.os.WindowsUtils;

public class Selenium2 {

@Test

public void testRegistry() {

WebDriver driver = new InternetExplorerDriver();

driver.get("D:\\demo\\checkbox.html");

String osname = WindowsUtils.readStringRegistryValue

("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\OS");

System.out.println(osname);

}

}

 

 

 

WindowsUtil也基于返回值的不同提供了多种方法来读取注册表的值,例子中返回的是String所以使用readStringRegistryValue(),还可以据不同的数据类型使用readIntegerRegistryValue(),readBooleanRegistryValue()根。

 

 

u 通过WebDriver修改windows注册表的值

package com.example.tests;

import static org.junit.Assert.*;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.ie.InternetExplorerDriver;

import org.openqa.selenium.os.WindowsUtils;

public class Selenium2 {

@Test

public void testRegistry() {

WebDriver driver = new InternetExplorerDriver();

driver.get("D:\\demo\\checkbox.html");

WindowsUtils.writeStringRegistryValue

("HKEY_CURRENT_USER\\SOFTWARE\\Selenium\\SeleniumVersion",

"2.24");

assertEquals("2.24",

WindowsUtils.readStringRegistryValue

("HKEY_CURRENT_USER\\SOFTWARE\\Selenium\\SeleniumVersion"));

}

}

 

writeStringRegistryValue()通过注册表的路径找到相应的位置,如果值存在则修改,如果不存在则新建一条新的,同时基于写入数据类型也提供了其他两种方法writeIntegerRegistryValue(),writeBooleanRegistryValue()

 

 

 

u 使用隐式的等待同步测试

Selenium WebDriver提供了隐式等待来同步测试。当使用了隐式等待执行测试的时候,如果WebDriver没有在DOM中找到元素,将继续等待,超出设定时间后则抛出找不到元素的异常。

换句话说,当查找元素或元素并没有立即出现的时候,隐式等待将等待一段时间再查找DOM。默认的时间是0 。

一旦设置了隐式等待,则它存在在整个WebDriver对象实例的生命周期中,但是,隐式的等待会让一个正常响应的应用的测试变慢,它将会在寻找每个元素的时候都进行等待,这样就增加了整个测试过程的执行时间。

package com.example.tests;

import static org.junit.Assert.*;

import java.util.concurrent.TimeUnit;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.ie.InternetExplorerDriver;

import org.openqa.selenium.os.WindowsUtils;

public class Selenium2 {

@Test

public void testWithImplicitWait() throws InterruptedException {

WebDriver driver = new InternetExplorerDriver();

driver.get

("http://demo.tutorialzine.com/2009/09/" + "simple-ajax-website-jquery/demo.html");

//等待10 

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

WebElement page4button = driver. findElement(By.linkText("Page 4"));

page4button.click();

WebElement message = driver.findElement(By.id("pageContent"));

//等待Ajax的内容出现 

Thread.sleep(4000);

assertTrue(message.getText().contains("Nunc nibh tortor"));

}

}

 

 

Selenium WebDriver提供了Timeouts接口来设置隐式等待。Timeouts接口下又提供了implicitlyWait()方法,接收一个查询元素所需要等待癿时间参数。

Thread.sleep(4000)意思义等待4秒钟,如果没有返句加上pageContent本身就存在,所以它癿内容就是最初没有点击时候文本,是我们所期望。。

 

u 使用显式的等待同步测试

Selenium WebDriver也提供了显式等待,相对亍隐式来说更好控制方法来同步测试。像隐式等待,你可以在执行下一次操作时,自定义等待条件。

显式等待叧需要执行在需要同步地方而影响脚本其他癿地方。

Selenium WebDriver提供了WebDriverWaitExpectedCondition类来执行显式等待。

ExpectedCondition类提供了一系列预定义好条件来等待。下面表格中显示了一些我们经常在自化测试中遇到常用条件。

预定义条件

方法名

元素可见可点击

elementToBeClickable(By locator)

元素被选中

elementToBeSelected(WebElement element)

存在一个元素

presenceOfElementLocated(By locator)

元素中出现指定癿文本

textToBePresentInElement(By locator, String text)

元素癿值

textToBePresentInElementValue(By locator, String text)

标题

titleContains(String title)

 

package com.example.tests;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.ie.InternetExplorerDriver;

import org.openqa.selenium.support.ui.*;

public class Selenium2 {

@Test

public void testWithImplicitWait() throws InterruptedException {

WebDriver driver = new InternetExplorerDriver();

driver.get("http://demo.tutorialzine.com/2009/09/simple-ajax-website-jquery/demo.html");

WebElement page4button = driver.findElement(By.linkText("Page 4"));

page4button.click();

//设置等待时间10 

WebDriverWait wait = new WebDriverWait(driver, 10);

//等待直到符合元素文本内容出现。 

wait.until(ExpectedConditions.textToBePresentInElement

(By.id("pageContent"),

"Nunc nibh tortor, " +

"congue pulvinar rhoncus quis, " +

"porta sed odio. Quisque ornare, " +

"velit elementum porta consequat, " +

"nibh augue tincidunt magna, " +

"at ullamcorper ligula felis vitae felis."));

 

WebDriverWait500毫秒调用一次ExpectedCondition直到正确的返回值。

可见返样好处就是随时控制所需要等待地方,更加精确控制所需要癿条件

 

 

u 使用自定义的期望条件同步测试

package com.example.tests;

import static org.junit.Assert.*;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.ie.InternetExplorerDriver;

import org.openqa.selenium.support.ui.*;

public class Selenium2 {

@Test

public void testWithImplicitWait() throws InterruptedException {

WebDriver driver = new InternetExplorerDriver();

driver.get("http://www.w3school.com.cn/" +

"ajax/ajax_example.asp");

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

//验证点击之前的文本 

assertTrue(driver.findElement

(By.cssSelector("#myDiv h3"))

.getText().contains("Let AJAX"));

button.click();

//设置等待时间为5 

WebDriverWait wait = new WebDriverWait(driver, 5);

//创建一个新的ExpecctedCondition接口,就必须实现apply方法 

WebElement message = wait.until

(new ExpectedCondition<WebElement>(){

public WebElement apply(WebDriver d){

return d.findElement(By.cssSelector("#myDiv p"));

}

});

//验证点击后的文本 

assertTrue(message.getText().contains("AJAX is"));

driver.close();

}

}  

这里通过ExpectedConditionWebDriverWait类我们自定义了一个期望条件。在这个例子中我们需要在5秒内定位到指定的元素,其实通过自身的presenceOfElementLocated(By locator)方法也能实现.

 

等待元素的属性值改变:

(new WebDriverWait(driver, 10)).until(

new ExpectedCondition<Boolean>()

{

public Boolean apply(WebDriver d)

{

return d.findElement(By.id("userName")).getAttribute("readonly").contains("true");

}});

 

如下例子也是等待某属性改变:

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

WebElement button =

driver.findElement(By.linkText("RUN CODE"));

button.click();

//设置等待时间为5 

WebDriverWait wait = new WebDriverWait(driver, 5);

//这里apply的返回值为Boolean

Boolean classname = wait.until

(new ExpectedCondition<Boolean>(){

public Boolean apply(WebDriver d){

return d.findElement(

By.cssSelector(".jq-codeDemo p"))

.getAttribute("class")

.contains("ohmy");

}

});

driver.close();

 

 

 

 

 

 

等待元素变为可见:

package com.example.tests;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.ie.InternetExplorerDriver;

import org.openqa.selenium.support.ui.*;

public class Selenium2 {

@Test

public void testWithImplicitWait() throws InterruptedException {

WebDriver driver = new InternetExplorerDriver();

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

WebElement button =

driver.findElement(By.linkText("RUN CODE"));

button.click();

//设置等待时间为5 

WebDriverWait wait = new WebDriverWait(driver, 5);

//创建一个新的ExpecctedCondition接口,就必须实现apply方法 

Boolean classname = wait.until

(new ExpectedCondition<Boolean>(){

public Boolean apply(WebDriver d){

return d.findElement(

By.cssSelector(".jq-codeDemo p"))

.isDisplayed();

}

});

driver.close();

}

}

 

 

等待DOM的事件

Web应用可能使用了AJAX的框架如jQuery来操作网页内容。例如,jQuery经常异步的会去从服务器加载一个很大的JSON文件。当jQuery正在处理文件的时候,测试可以使用active属性。自定义的等待可以通过执行一段JavaScript代码并检查返回值来完成。

(new WebDriverWait(driver, 10)).until(

new ExpectedCondition<Boolean>()

{

public Boolean apply(WebDriver d)

 {

JavascriptExecutor js = (JavascriptExecutor) d;

return (Boolean)js.executeScript("return jQuery.active == 0");

}});

 

u 检查元素是否存在

package com.example.tests;

import static org.junit.Assert.*;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.ie.InternetExplorerDriver;

public class Selenium2 {

WebDriver driver = new InternetExplorerDriver();

@Test

public void testisElementPresent(){

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

driver.findElement(By.id("kw")).sendKeys("selenium");

//判断搜索按钮是否存在 

if(isElementPresent(By.id("su1"))){

//点击按钮 

driver.findElement(By.id("su")).click();

}else{

fail("元素不存在");

}

}

private boolean isElementPresent(By by)

{

try

{

driver.findElement(by);

return true;

}

catch (Exception e)

{

e.printStackTrace();

return false;

}

}

}

 

 

 

 

 

 

u 检查元素的状态

isSelected()

检查元素是否被选中(单选,多选,下拉框)

disDisplayed()

检查元素是否可见

 

package com.example.tests;

import static org.junit.Assert.*;

import java.util.*;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.firefox.FirefoxDriver;

public class Selenium2 {

@Test

public void testRadioButton() {

WebDriver driver = new FirefoxDriver();

driver.get("D:\\demo\\RadioButton.html");

//使用value值来定位单选按钮 

WebElement apple =

driver.findElement(By.cssSelector("input[value='Apple']"));

//检查是否已选择,如果没有则点击选择 

if(!apple.isSelected()){

apple.click();

}

//验证apple选项已经选中 

assertTrue(apple.isSelected());

//也可以得到所有的单选按钮 

List<WebElement> fruit =

driver.findElements(By.name("fruit"));

//查询Orange选项是否存在,如果存在则选择 

for(WebElement allFruit : fruit){

if(allFruit.getAttribute("value").equals("Orange")){

if(!allFruit.isSelected()){

allFruit.click();

assertTrue(allFruit.isSelected());

break;

}

 

 

 

 

 

 

u 通过名称识别和处理一个弹出窗口

package com.example.tests;

import static org.junit.Assert.*;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.firefox.FirefoxDriver;

public class Selenium2 {

WebDriver driver = new FirefoxDriver();

@Test

public void testWindowPopup(){

driver.get("D:\\demo\\window.html");

//保存父窗口 

String parentWindowId = driver.getWindowHandle();

//点击按钮弹出窗口 

WebElement helpButton = driver.findElement(By.id("helpbutton1"));

helpButton.click();

try

 {

//转到HelpWindow

driver.switchTo().window("HelpWindow");

}

catch (NoSuchWindowException e)

{

e.printStackTrace();

}

//验证新窗口里的文本 

assertEquals("PopUpWindow", driver.findElement(By.tagName("p")).getText());

//关闭子窗口 

driver.close();

//回到父窗口 

driver.switchTo().window(parentWindowId);

//验证父窗口的title

assertTrue(driver.getTitle().equals("help"));

driver.close();

}

}

 

 

 

u 通过标题识别处理一个弹出窗口

很多时候开发人员并没有给弹出的窗口分配一个name属性。这种情况下,我们可以使用handle属性。但是,handle的值是不停的变化的,这让识别窗口变的有些困难,尤其是多个窗口的时候。我们使用handletitle来识别一个弹出窗口。

package com.example.tests;

import static org.junit.Assert.*;

import java.util.Set;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.firefox.FirefoxDriver;

public class Selenium2 {

WebDriver driver = new FirefoxDriver();

@Test

public void testWindowPopup(){

driver.get("D:\\demo\\window.html");

//保存父窗口 

String parentWindowId = driver.getWindowHandle();

//点击按钮弹出窗口 

WebElement helpButton =

driver.findElement(By.id("helpbutton2"));

helpButton.click();

//得到所有的窗口 

Set<String> allWindowsId = driver.getWindowHandles();

//通过title得到新的窗口 

for (String windowId : allWindowsId)

 {

if (driver.switchTo().window(windowId)

.getTitle().equals("PopUpWindow"))

{

driver.switchTo().window(windowId);

break;

}

}

//验证新窗口的文本 

assertEquals("PopUpWindow", driver.findElement(By.tagName("p")).getText());

//关闭弹出窗口 

driver.close();

//关闭父窗口 

driver.switchTo().window(parentWindowId);

driver.close();

}

}

u 通过网页内容识别处理一个弹出窗口

 

package com.example.tests;

import static org.junit.Assert.*;

import java.util.Set;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.firefox.FirefoxDriver;

public class Selenium2 {

WebDriver driver = new FirefoxDriver();

@Test

public void testWindowPopup(){

driver.get("D:\\demo\\window.html");

//保存父窗口 

String parentWindowId = driver.getWindowHandle();

//点击按钮弹出窗口 

WebElement helpButton =

driver.findElement(By.id("helpbutton2"));

helpButton.click();

//得到所有的窗口 

Set<String> allWindowsId = driver.getWindowHandles();

//通过查找页面内容得到新的窗口 

for (String windowId : allWindowsId) {

driver.switchTo().window(windowId);

if (driver.getPageSource().contains("Welcome")){

driver.switchTo().window(windowId);

break;

}

}

//验证新窗口的文本 

assertEquals("PopUpWindow",

driver.findElement(By.tagName("p")).getText());

//关闭弹出窗口 

driver.close();

//关闭父窗口 

driver.switchTo().window(parentWindowId);

driver.close();

}

}

 

通过driver.getPageSource()方法得到页面的html内容,再调用contains()方法来判断是否含有指定的内容。这样做的缺点就是如果页面内容很多,获得的速度会慢,而且contains()里面查找内容必须是唯一,否则可能识别的窗口不是你所期望的。

 

 

 

 

u 处理一个简单的JavaScript警告窗

//获取alert窗口 

Alert alertBox = driver.switchTo().alert();

alertBox.accept();

//验证alert窗口里的文字 

assertEquals("Hello World",alertBox.getText());

driver.close();

 

driver.switchTo().alert()将窗口移劢到警告框上。

alert.getText()得到警告框上癿信息。

如果找到警告框则会抛出NoAlertPresentException异常。

 

 

 

u 处理一个确认框

package com.example.tests;

import static org.junit.Assert.*;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.firefox.FirefoxDriver;

public class Selenium2 {

WebDriver driver = new FirefoxDriver();

@Test

public void testWindowPopup(){

driver.get("D:\\demo\\alert.html");

//点击确定按钮 

getConfirmBox().accept();

//验证点击后的文字 

assertEquals("你点击了确定按钮!",

driver.findElement(By.cssSelector("span")).getText());

//点击取消按钮 

getConfirmBox().dismiss();

assertEquals("你点击了取消按钮!",

driver.findElement(By.cssSelector("span")).getText());

driver.close();

}

//封装得到窗口的方法 

private Alert getConfirmBox(){

//点击按钮弹出确认提示框 

WebElement button = driver.findElement(By.id("confirm"));

button.click();

//获取确认提示框 

Alert confirmBox = driver.switchTo().alert();

assertEquals("我是确认提示框!",confirmBox.getText());

return confirmBox;

}

}

 

点击确认是使用accept()方法,点击取消使用dismiss()方法。

 

u 处理一个提示框

package com.example.tests;

import static org.junit.Assert.*;

import org.junit.*;

import org.openqa.selenium.*;

import org.openqa.selenium.firefox.FirefoxDriver;

public class Selenium2 {

WebDriver driver = new FirefoxDriver();

@Test

public void testPromptAlert(){

driver.get("D:\\demo\\alert.html");

WebElement button = driver.findElement(By.id("prompt"));

button.click();

//获得提示框 

Alert promptAlert = driver.switchTo().alert();

assertEquals("点都点了,就输入点什么吧",promptAlert.getText());

//输入一些数据 

promptAlert.sendKeys("洛阳亲友如相问,就说我在写代码");

//点击确定按钮 

promptAlert.accept();

//验证输入的数据 

String actualTest = driver.findElement(By.tagName("span"))

.getText();

assertEquals("洛阳亲友如相问,就说我在写代码", actualTest);

driver.close();

}

}

 

 

 

 

u 识别处理框架

//通过id定位到左边的框架 

driver.switchTo().frame("left");

String leftMsg = driver.findElement(By.tagName("p")).getText();

assertEquals("i am left page",leftMsg);

//回到初始的焦点 

driver.switchTo().defaultContent();

//通过name定位到右边的框架 

driver.switchTo().frame("right");

String rightMsg = driver.findElement(By.tagName("p")).getText();

assertEquals("i am right page",rightMsg);

driver.close();

 

 

通过index获取frame框架:

//通过index来定位框架 

driver.switchTo().frame(1);

//验证中间框架的文本 

String middleMsg = driver.findElement(By.tagName("p"))

.getText();

assertEquals("i am middle page",middleMsg);

u 通过页面内容识别和处理框架

//得到所有的frame元素 

List<WebElement> frames = driver.findElements(By.tagName("frame"));

//通过页面的内容得到中间的框架 

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

 {

driver.switchTo().frame(i);

if (driver.getPageSource().contains("middle"))

{

break;

//没有匹配的时候需要回到最初的页面 

}

else

{

driver.switchTo().defaultContent();

}

String actualText = driver.findElement(By.tagName("p")).getText();

assertEquals("i am middle page", actualText);

 

u 处理IFRAM

//首先获得父窗口 

driver.switchTo().frame("left");

//取得iframe元素 

WebElement weiboIframe = driver.findElement(By.tagName("iframe"));

//获得iframe窗口 

driver.switchTo().frame(weiboIframe);

//验证iframe里面的页面内容 

String actualText = driver.findElement(By.linkText("新浪微博")).getText();

assertEquals("新浪微博", actualText);

driver.switchTo().defaultContent();

 

 

定位frame中的元素

场景

处理frame需要用到2个方法,分别是switchTo().frame(element|index|id)和switchTo.defaultContent()

switchTo().frame()方法的参数值得一提。其支持

  • WebElement, 可以传入一个已经定位的frame元素。如 switchTo().frame(dr.findElement(By.id("myFrame")))
  • int index, 可以传入页面上frame的索引,如0表示第1个frame
  • String id, 可以传入frame的id

switchTo().frame()方法把当前定位的主体切换了frame里。怎么理解这句话呢?我们可以从frame的实质去理解。frame中实际上是嵌入了另一个页面,而webdriver每次只能在一个页面识别,因此才需要用switch_to.frame方法去获取frame中嵌入的页面,对那个页面里的元素进行定位。

switchTo.defaultContent方法的话则是从frame中嵌入的页面里跳出,跳回到最外面的原始页面中。

如果页面上只有1个frame的话那么这一切都是很好理解的,但如果页面上有多个frame,情况有稍微有点复杂了。

代码

下面的代码中frame.html里有个id为f1的frame,而f1中又嵌入了id为f2的frame,该frame加载了百度的首页。

frame.html

<html>

<head>

<meta http-equiv="content-type" content="text/html;charset=utf-8" />

<title>frame</title>

<script type="text/javascript" async="" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" />

<script type="text/javascript">

$(document).ready(function(){

});

</script>

</head>

<body>

<div class="row-fluid">

<div class="span10 well">

<h3>frame</h3>

<iframe id="f1" src="inner.html" width="800", height="600"></iframe>

</div>

</div>

</body>

<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>

</html>

inner.html

<html>

<head>

<meta http-equiv="content-type" content="text/html;charset=utf-8" />

<title>inner</title>

</head>

<body>

<div class="row-fluid">

<div class="span6 well">

<h3>inner</h3>

<iframe id="f2" src="http://www.baidu.com" width="700" height="500"></iframe>

<a href="javascript:alert('watir-webdriver better than selenium webdriver;')">click</a>

</div>

</div>

</body>

</html>

frame.java

public class Frame {

public static void main(String[] args) throws InterruptedException {

WebDriver dr = new ChromeDriver();

File file = new File("src/frame.html");

String filePath = "file:///" + file.getAbsolutePath();

System.out.printf("now accesss %s \n", filePath);

dr.get(filePath);

Thread.sleep(1000);

// 先到f1再到f2

dr.switchTo().frame("f1");

dr.switchTo().frame("f2");

// 往f2中的百度关键字文本框中输入内容

dr.findElement(By.id("kw")).sendKeys("watir-webdriver");

Thread.sleep(1000);

// 直接跳出所有frame

dr.switchTo().defaultContent();

// 再到f1

dr.switchTo().frame("f1");

dr.findElement(By.linkText("click")).click();

Thread.sleep(1000);

System.out.println("browser will be close");

dr.quit();

}

}

讨论

假设页面上有A、B两个frame,其中B在A内,那么定位B中的内容则需要先到A,然后再到B。如果是定位A中的内容,那么直接switch_to.frame('A')就可以了;

页面中使用frame会影响页面渲染速度,如果你遇到页面中有多个frame的情况,你完全可以提出1个页面前端性能的缺陷;

如果实在搞不定页面上的frame,送你一句歌词:也许放弃才能靠近你。那么及时放弃跟此frame相关的用例才是明智之举;

 

action

场景

由于webdriver是要模拟真实的用户操作,因此webdriver的Action类中提供了很多与操作有关的方法。

下面列举一下Action类的一些主要方法

  • keyDown。模拟按键按下
  • keyUp。模拟按键弹起
  • click
  • sendKeys
  • doubleClick。鼠标左键双击
  • clickAndHold。鼠标左键点击住不放
  • release。鼠标左键弹起,可以与click_and_hold配合使用
  • moveToElement。把鼠标移动到元素的中心点
  • contextClick。鼠标右键点击
  • dragAndDrop。拖拽

代码

Actions action = new Actions(driver)

action.keyDown(Keys.SHIFT).

click(element).

click(second_element).

keyUp(Keys.SHIFT).

dragAndDrop(element, third_element).

build().

perform()

讨论

具体使用方法可以参考api文档。action的api文档算是比较全面了。

上传文件

场景

上传文件的方法是找到上传文件的对象,通常是的对象。然后直接往这个对象sendKeys,传入需要上传文件的正确路径。绝对路径和相对路径都可以,但是上传的文件必须存在,否则会报错。

代码

upload_file.html

<html>

<head>

<meta http-equiv="content-type" content="text/html;charset=utf-8" />

<title>upload_file</title>

<script type="text/javascript" async="" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" />

<script type="text/javascript">

</script>

</head>

<body>

<div class="row-fluid">

<div class="span6 well">

<h3>upload_file</h3>

<input type="file" name="file" />

</div>

</div>

</body>

<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>

</html>

upload_file.java

import java.io.File;

import java.util.List;

import org.openqa.selenium.Alert;

import org.openqa.selenium.By;

import org.openqa.selenium.Keys;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.chrome.ChromeDriver;

public class Upload {

public static void main(String[] args) throws InterruptedException {

WebDriver dr = new ChromeDriver();

File file = new File("src/upload_file.html");

String filePath = "file:///" + file.getAbsolutePath();

System.out.printf("now accesss %s \n", filePath);

dr.get(filePath);

Thread.sleep(1000);

dr.findElement(By.cssSelector("input[type=file]")).sendKeys("src/navs.html");

Thread.sleep(1000);

System.out.println("browser will be close");

dr.quit();

}

}

 

执行js

场景

如果你熟悉js的话,那么使用webdriver执行js就是一件很高效的事情了。在webdriver脚本中直接执行js的好处很多,这里就不一一枚举了。

webdriver提供了JavascriptExecutor(dr).executeScript()接口来帮助我们完成这一工作。在实际的测试脚本中,以下两种场景是经常遇到的

  • 在页面直接执行一段js
  • 在某个已经定位的元素的上执行js

代码

下面的代码演示了如何在页面以及在已经定位的元素上执行js

js.html

<html>

<head>

<meta http-equiv="content-type" content="text/html;charset=utf-8" />

<title>js</title>

<script type="text/javascript" async="" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" />

<script type="text/javascript">

$(document).ready(function(){

$('#tooltip').tooltip({"placement": "right"});

});

</script>

</head>

<body>

<h3>js</h3>

<div class="row-fluid">

<div class="span6 well">

<a id="tooltip" href="#" data-toggle="tooltip" title="watir-webdriver better than selenium-webdriver">hover to see tooltip</a>

<a class="btn">Button</a>

</div>

</div>

</body>

<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>

</html>

js.java

public class Js {

public static void main(String[] args) throws InterruptedException {

WebDriver dr = new ChromeDriver();

File file = new File("src/js.html");

String filePath = "file:///" + file.getAbsolutePath();

System.out.printf("now accesss %s \n", filePath);

dr.get(filePath);

Thread.sleep(1000);

// 在页面上直接执行js

((JavascriptExecutor)dr).executeScript("$('#tooltip').fadeOut();");

Thread.sleep(1000);

// 在已经定位的元素上执行js

WebElement button = dr.findElement(By.className("btn"));

((JavascriptExecutor)dr).executeScript("$(arguments[0]).fadeOut();", button);

Thread.sleep(1000);

System.out.println("browser will be close");

dr.quit();

}

}

 

前进和后退

场景

说实话,这两个功能一般不太常用。所能想到的场景大概也就是在几个页面间来回跳转,省去每次都get url。

代码

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;

public class ForwardAndBack {

public static void main(String[] args) throws InterruptedException {

WebDriver dr = new ChromeDriver();

Thread.sleep(2000);

String firstUrl = "http://www.baidu.com";

System.out.printf("now accesss %s \n", firstUrl);

dr.get(firstUrl);

Thread.sleep(1000);

String secondUrl = "http://www.soso.com";

System.out.printf("now accesss %s \n", secondUrl);

dr.get(secondUrl);

Thread.sleep(1000);

System.out.printf("now back to %s \n", firstUrl);

dr.navigate().back();

Thread.sleep(1000);

System.out.printf("forward to %s \n", secondUrl);

dr.navigate().forward();

Thread.sleep(1000);

System.out.println("browser will be close");

dr.quit();

}

}

定位一组对象

场景

从上一节的例子中可以看出,webdriver可以很方便的使用findElement方法来定位某个特定的对象,不过有时候我们却需要定位一组对象,这时候就需要使用findElements方法。

定位一组对象一般用于以下场景:

  • 批量操作对象,比如将页面上所有的checkbox都勾上
  • 先获取一组对象,再在这组对象中过滤出需要具体定位的一些对象。比如定位出页面上所有的checkbox,然后选择最后一个

代码

checkbox.html

<html>

<head>

<meta http-equiv="content-type" content="text/html;charset=utf-8" />

<title>Checkbox</title>

<script type="text/javascript" async="" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" />

<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>

</head>

<body>

<h3>checkbox</h3>

<div class="well">

<form class="form-horizontal">

<div class="control-group">

<label class="control-label" for="c1">checkbox1</label>

<div class="controls">

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

</div>

</div>

<div class="control-group">

<label class="control-label" for="c2">checkbox2</label>

<div class="controls">

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

</div>

</div>

<div class="control-group">

<label class="control-label" for="c3">checkbox3</label>

<div class="controls">

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

</div>

</div>

<div class="control-group">

<label class="control-label" for="r">radio</label>

<div class="controls">

<input type="radio" id="r" />

</div>

</div>

</form>

</div>

</body>

</html>

find_element.java

public class SimpleLocate {

public static void main(String[] args) throws InterruptedException {

WebDriver dr = new ChromeDriver();

File file = new File("src/checkbox.html");

String filePath = "file:///" + file.getAbsolutePath();

System.out.printf("now accesss %s \n", filePath);

dr.get(filePath);

Thread.sleep(1000);

// 选择所有的checkbox并全部勾上

List<WebElement> checkboxes = dr.findElements(By.cssSelector("input[type=checkbox]"));

for(WebElement checkbox : checkboxes) {

checkbox.click();

}

dr.navigate().refresh();

// 打印当前页面上有多少个checkbox

System.out.printf("%d\n", checkboxes.size());

// 选择页面上所有的input,然后从中过滤出所有的checkbox并勾选之

List<WebElement> inputs = dr.findElements(By.tagName("input"));

for(WebElement input : inputs){

if(input.getAttribute("type").equals("checkbox")){

input.click();

}

}

// 把页面上最后1个checkbox的勾给去掉

List<WebElement> allCheckboxes = dr.findElements(By.cssSelector("input[type=checkbox]"));

allCheckboxes.get(allCheckboxes.size() - 1).click();

Thread.sleep(1000);

System.out.println("browser will be close");

dr.quit();

}

}

讨论

checkbox.html必须与find_elments.rb在同一级目录下

操作测试对象

场景

定位到具体的对象后,我们就可以对这个对象进行具体的操作,比如先前已经看到过的点击操作(click)。一般来说,webdriver中比较常用的操作对象的方法有下面几个

  • click 点击对象
  • sendKeys 在对象上模拟按键输入
  • clear 清除对象的内容,如果可以的话

代码

下面的代码演示了如何点击元素,如何往文本框中输入文字以及如何清空文字。

operate_element.html

<html>

<head>

<meta http-equiv="content-type" content="text/html;charset=utf-8" />

<title>Level Locate</title>

<script type="text/javascript" async="" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" />

</head>

<body>

<h3>Level locate</h3>

<div class="span3">

<div class="well">

<div class="dropdown">

<a class="dropdown-toggle" data-toggle="dropdown" href="#">Link1</a>

<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel" id="dropdown1" >

<li><a tabindex="-1" href="#">Action</a></li>

<li><a tabindex="-1" href="#">Another action</a></li>

<li><a tabindex="-1" href="#">Something else here</a></li>

<li class="divider"></li>

<li><a tabindex="-1" href="#">Separated link</a></li>

</ul>

</div>

</div>

</div>

<div class="span3">

<div class="well">

<div class="dropdown">

<a class="dropdown-toggle" data-toggle="dropdown" href="#">Link2</a>

<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel" >

<li><a tabindex="-1" href="#">Action</a></li>

<li><a tabindex="-1" href="#">Another action</a></li>

<li><a tabindex="-1" href="#">Something else here</a></li>

<li class="divider"></li>

<li><a tabindex="-1" href="#">Separated link</a></li>

</ul>

</div>

</div>

</div>

</body>

<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>

</html>

operate_element.java

import java.io.File;

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.chrome.ChromeDriver;

public class OperateElement {

public static void main(String[] args) throws InterruptedException {

WebDriver dr = new ChromeDriver();

File file = new File("src/operate_element.html");

String filePath = "file:///" + file.getAbsolutePath();

System.out.printf("now accesss %s \n", filePath);

dr.get(filePath);

Thread.sleep(1000);

// click

dr.findElement(By.linkText("Link1")).click();

Thread.sleep(1000);

dr.findElement(By.linkText("Link1")).click();

// send_keys

WebElement element = dr.findElement(By.name("q"));

element.sendKeys("something");

Thread.sleep(1000);

// clear

element.clear();

Thread.sleep(1000);

System.out.println("browser will be close");

dr.quit();

}

}

send keys模拟按键输入

场景

sendKeys方法可以模拟一些组合键操作,比如ctrl+a等。另外有时候我们需要在测试时使用tab键将焦点转移到下一个元素,这时候也需要sendKeys。在某些更复杂的情况下,还会出现使用sendKeys来模拟上下键来操作下拉列表的情况。

代码

下面的代码演示了如何将A多行文本框中的内容清空并复制到B文本框中。

send_keys.html

<html>

<head>

<meta http-equiv="content-type" content="text/html;charset=utf-8" />

<title>send keys</title>

<script type="text/javascript" async="" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" />

</head>

<body>

<h3>send keys</h3>

<div class="row-fluid">

<div class="span3">

<div class="well">

<label>A</label>

<textarea rows="10", cols="10" id="A">I think watir-webdriver is better than selenium-webdriver</textarea>

</div>

</div>

<div class="span3">

<div class="well">

<label>B</label>

<textarea rows="10", cols="10" id="B"></textarea>

</div>

</div>

</div>

</body>

<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>

</html>

send_keys.java

import java.io.File;

import org.openqa.selenium.By;

import org.openqa.selenium.Keys;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;

public class SendKeys {

public static void main(String[] args) throws InterruptedException {

WebDriver dr = new ChromeDriver();

File file = new File("src/send_keys.html");

String filePath = "file:///" + file.getAbsolutePath();

System.out.printf("now accesss %s \n", filePath);

dr.get(filePath);

Thread.sleep(1000);

// copy content of A

dr.findElement(By.id("A")).sendKeys(Keys.chord(Keys.CONTROL + "a"));

Thread.sleep(1000);

dr.findElement(By.id("A")).sendKeys(Keys.chord(Keys.CONTROL + "x"));

// paste to B

dr.findElement(By.id("B")).sendKeys(Keys.chord(Keys.CONTROL + "v"));

// SendKeys to A

dr.findElement(By.id("A")).sendKeys(Keys.chord("watir webdriver is better than selenium webdriver"));

Thread.sleep(1000);

System.out.println("browser will be close");

dr.quit();

}

}

处理button group

场景

button group就是按钮组,将一组按钮排列在一起。处理这种对象的思路一般是先找到button group的包裹(wrapper)div,然后通过层级定位,用index或属性去定位更具体的按钮。

代码

下面的代码演示了如何找到second这个按钮。其处理方法是先找到button group的父div,class为btn-group的div,然后再找到下面所有的div(也就是button),返回text是second的div。

button_group.html

<html>

<head>

<meta http-equiv="content-type" content="text/html;charset=utf-8" />

<title>button group</title>

<script type="text/javascript" async="" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" />

<script type="text/javascript">

$(document).ready(function(){

$('.btn').click(function(){

alert($(this).text());

});

});

</script>

</head>

<body>

<h3>button group</h3>

<div class="row-fluid">

<div class="span3">

<div class="well">

<div class="btn-toolbar">

<div class="btn-group">

<div class="btn">first</div>

<div class="btn">second</div>

<div class="btn">third</div>

</div>

</div>

</div>

</div>

</div>

</body>

<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>

</html>

button_group.java

import java.io.File;

import java.util.List;

import org.openqa.selenium.By;

import org.openqa.selenium.Keys;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.chrome.ChromeDriver;

public class ButtonGroup {

public static void main(String[] args) throws InterruptedException {

WebDriver dr = new ChromeDriver();

File file = new File("src/button_group.html");

String filePath = "file:///" + file.getAbsolutePath();

System.out.printf("now accesss %s \n", filePath);

dr.get(filePath);

Thread.sleep(1000);

// 定位text是second的按钮

List<WebElement> btns = dr.findElement(By.className("btn-group")).findElements(By.className("btn"));

for(WebElement btn : btns){

if(btn.getText().equals("second")){

btn.click();

break;

}

}

Thread.sleep(1000);

System.out.println("browser will be close");

dr.quit();

}

}

讨论

自己查资料搞清楚detect方法的作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

py编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值