webdriver实用指南java版本
目录如下
- 启动浏览器
- 关闭浏览器
- 浏览器最大化
- 设置浏览器大小
- 访问链接
- 打印当前页面的title及url
- 前进和后退
- 简单的对象定位
- 定位一组对象
- 层级定位
- 操作测试对象
- send keys模拟按键输入
- 处理button group
- 处理button dropdown
- 处理navs
- 处理面包屑
- 处理对话框新式的模态窗口
- 获取测试对象的属性及内容
- 获取测试对象的css属性
- 获取测试对象的状态
- 处理表单元素
- 执行js
- 处理alert/confirm/prompt
- wait
- 定位frame中的元素
- action
- 上传文件
- 下载
- 超时设置
- Remote Webdriver
- cookie与自动登陆
启动浏览器
场景
在使用webdriver进行测试时启动浏览器无疑是必须的前置工作。
代码
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class StartBrowser {
public static void main(String[] args) {
WebDriver dr = new ChromeDriver();
}
}
关闭浏览器
场景
在脚本运行完毕或者测试代码结束的时候关闭浏览器是非常自然的事情,就像在吃完饭后就把餐桌收拾干净一样。
关闭浏览器有两种方式:
- close方法
- quit方法
close方法关闭当前的浏览器窗口,quit方法不仅关闭窗口,还会彻底的退出webdriver,释放与driver server之间的连接。所以简单来说quit是更加彻底的close,quit会更好的释放资源,适合强迫症和完美主义者。
代码
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class CloseBrowser {
public static void main(String[] args) {
WebDriver dr = new ChromeDriver();
System.out.println("browser will be closed");
dr.quit();
System.out.println("browser is closed");
}
}
浏览器最大化
场景
当我们在测试中使用一些基于图像和坐标的辅助测试工具时,我们就会需要使浏览器在每次测试时保存最大化,以便在同一分辨率下进行图像比对和坐标点选。
举例来说,如果在webdriver测试中使用了sikuli来对flash插件进行操作的话,把浏览器最大化无疑是一个比较简单的保证分辨率统一的解决方案。
代码
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class Maximize {
public static void main(String[] args) throws InterruptedException {
WebDriver dr = new ChromeDriver();
Thread.sleep(2000);
System.out.println("maximize browser");
dr.manage().window().maximize();
Thread.sleep(2000);
System.out.println("browser will be close");
dr.quit();
}
}
设置浏览器大小
场景
设置浏览器窗口的大小有下面两个比较常见的用途:
- 在统一的浏览器大小下运行用例,可以比较容易的跟一些基于图像比对的工具进行结合,提升测试的灵活性及普遍适用性。比如可以跟sikuli结合,使用sikuli操作flash;
- 在不同的浏览器大小下访问测试站点,对测试页面截图并保存,然后观察或使用图像比对工具对被测页面的前端样式进行评测。比如可以将浏览器设置成移动端大小(320x480),然后访问移动站点,对其样式进行评估;
代码
将浏览器调整成移动端大小,然后访问移动站点,对移动站点的样式进行评估。
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class CloseBrowser {
public static void main(String[] args) {
WebDriver dr = new ChromeDriver();
dr.manager().Window().setSize(new Dimension(600,800))
System.out.println("browser will be closed");
dr.quit();
System.out.println("browser is closed");
}
}
讨论
webdriver提供了很多调整浏览器窗口的接口,比如move_to(移动窗口),position(设置或获取浏览器的位置)。在一般情况下这些功能并不常用。
访问链接
情景
web UI测试里最简单也是最基本的事情就是访问1个链接了。
webdriver的api里有2种访问url的方式,分别是get和navigate.to方法。一般情况下建议使用get,因为其字母比较少,不太容易出错。
代码
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class Get {
public static void main(String[] args) throws InterruptedException {
WebDriver dr = new ChromeDriver();
Thread.sleep(2000);
String url = "http://www.baidu.com";
System.out.printf("now accesss %s \n", url);
dr.get(url);
Thread.sleep(2000);
System.out.println("browser will be close");
dr.quit();
}
}
讨论
navigate方法实际上会产生1个Navigator对象,其封装了与导航相关的一些方法,比如前进后退等。
打印当前页面的title及url
情景
测试中,访问1个页面然后判断其title是否符合预期是很常见的1个用例,所谓用例不够,title来凑就是这个道理。更具体一点,假设1个页面的title应该是'hello world', 那么可以写这样的一个用例:访问该页面,获取该页面的title,判断获取的值是否等于'hello world'。
获取当前页面的url也是非常重要的一个操作。在某些情况下,你访问一个url,这时系统会自动对这个url进行跳转,这就是所谓的'重定向'。一般测试重定向的方法是访问这个url,然后等待页面重定向完毕之后,获取当前页面的url,判断该url是否符合预期。另外的一个常见的测试场景是提交了一个表单,如果表单内容通过了验证,那么则会跳转到一个新页面,如果未通过验证,则会停留在当前页面,此时获取当前页面的url则可以帮助我们判断表单提交的跳转是否符合预期。更具体一点,假如你在测试一个登陆页面,输入正确的登陆信息后,会跳转到系统首页。获取跳转后的url然后判断其是否与系统首页的url相符将是一个很不错的用例。
代码
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class TitleAndUrl {
public static void main(String[] args) throws InterruptedException {
WebDriver dr = new ChromeDriver();
Thread.sleep(2000);
String url = "http://www.baidu.com";
System.out.printf("now accesss %s \n", url);
dr.get(url);
Thread.sleep(2000);
System.out.printf("title of current page is %s\n", dr.getTitle());
System.out.printf("url of current page is %s\n", dr.getCurrentUrl());
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的核心内容,其中操作又是建立在定位的基础之上,因此对象定位就越发显得重要了。
定位对象的目的一般有下面几种
- 操作对象
- 获得对象的属性,如获得测试对象的class属性,name属性等等
- 获得对象的text
- 获得对象的数量
webdriver提供了一系列的对象定位方法,常用的有以下几种
- id
- name
- class name
- link text
- partial link text
- tag name
- xpath
- css selector
代码
html代码 form.html
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>Form</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>simple login form</h3>
<form class="form-horizontal">
<div class="control-group">
<label class="control-label" for="inputEmail">Email</label>
<div class="controls">
<input type="text" id="inputEmail" placeholder="Email" name="email">
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputPassword">Password</label>
<div class="controls">
<input type="password" id="inputPassword" placeholder="Password" name="password">
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox"> Remember me
</label>
<button type="submit" class="btn">Sign in</button>
<a href="#">register</a>
</div>
</div>
</form>
</body>
</html>
java代码 simple_locate.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;
import org.openqa.selenium.JavascriptExecutor;
public class SimpleLocate {
public static void main(String[] args) throws InterruptedException {
WebDriver dr = new ChromeDriver();
File file = new File("src/form.html");
String filePath = "file:///" + file.getAbsolutePath();
System.out.printf("now accesss %s \n", filePath);
dr.get(filePath);
Thread.sleep(2000);
// by id
dr.findElement(By.id("inputEmail")).click();
Thread.sleep(1000);
// by name
dr.findElement(By.name("password"));
Thread.sleep(1000);
// by tagname
String classOfForm = dr.findElement(By.tagName("form")).getAttribute("class");
System.out.printf("%s\n", classOfForm);
Thread.sleep(1000);
// by link text
WebElement link = dr.findElement(By.linkText("register"));
((JavascriptExecutor)dr).executeScript("$(arguments[0]).fadeOut().fadeIn()", link);
Thread.sleep(1000);
// by partial link test
WebElement sameLink = dr.findElement(By.partialLinkText("reg"));
((JavascriptExecutor)dr).executeScript("$(arguments[0]).fadeOut().fadeIn()", sameLink);
Thread.sleep(1000);
// by css selector
WebElement div = dr.findElement(By.cssSelector(".controls"));
((JavascriptExecutor)dr).executeScript("$(arguments[0]).fadeOut().fadeIn()", div);
Thread.sleep(1000);
// by xpath
dr.findElement(By.xpath("/html/body/form/div[3]/div/label/input")).click();
Thread.sleep(1000);
System.out.println("browser will be close");
dr.quit();
}
}
讨论
上面例子里由于html文件中引用了jquery,所以在执行js时可以使用jquery的$()及fadeIn()等方法。如果你测试的页面没用包含jquery的话,这些方法是无效的。
定位一组对象
场景
从上一节的例子中可以看出,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
import java.io.File;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.JavascriptExecutor;
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在同一级目录下
层级定位
场景
在实际的项目测试中,经常会有这样的需求:页面上有很多个属性基本相同的元素,现在需要具体定位到其中的一个。由于属性基本相当,所以在定位的时候会有些麻烦,这时候就需要用到层级定位。先定位父元素,然后再通过父元素定位子孙元素。
代码
下面的代码演示了如何通过层级定位来定位下拉菜单中的某一项。由于两个下拉菜单中每个选项的link text都相同,href也一样,所以在这里就需要使用层级定位了。
具体思路是:先点击显示出1个下拉菜单,然后再定位到该下拉菜单所在的ul,再定位这个ul下的某个具体的link。在这里,我们定位第1个下拉菜单中的Another action这个选项。
level_locate.html
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>Level Locate</title>
<script type="text/javascript" async="" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></