IDEA+Webdriver+Junit测试分享【详细】(转载自https://blog.csdn.net/yangdengcheng/article/details/80265628)
一、环境搭建
- 访问oracle的官网下载最新版本的 jdk
- 配置环境变量【详情请百度查看如何配置JAVA的环境变量】
- 编译工具IDEA【根据个人爱好选择,也可以选用Eclipse】
- 需要安装Maven,基于Maven构建项目【注意我选择的selenium是2.45.0的版本】
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.45.0</version>
</dependency>
- 检查相关环境的配置是否完备,打开终端,输入以下内容
java -version
// 如果显示下面内容说明Java环境已经安装成功
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=gasp
openjdk version "1.8.0_141"
OpenJDK Runtime Environment (build 1.8.0_141-8u141-b15-3-b15)
OpenJDK 64-Bit Server VM (build 25.141-b15, mixed mode)
mvn -version
// 如果显示一下内容说明Mvn环境已经配置成功
Apache Maven 3.5.3 (3383c37e1f9e9b3bc3df5050c29c8aff9f295297; 2018-02-25T03:49:05+08:00)
Maven home: /opt/maven/apache-maven-3.5.3
Java version: 1.8.0_141, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-8-openjdk-amd64/jre
Default locale: zh_CN, platform encoding: UTF-8
OS name: "linux", version: "4.14.0-deepin2-amd64", arch: "amd64", family: "unix"
-
安装浏览器驱动【Webdriver支持多个浏览器,用的比较多的就是Chrome、IE、FireFox
注意安装驱动的时候要注意以下几点:
- 浏览器的版本号以及对应的驱动版本【后面我会说到】
- 不同操作系统使用不同的浏览器驱动
- 附上相关驱动下载地址 IE、Chrome、FireFox
二、第一个简单程序
-
IDEA构建Maven项目
- 创建项目
- Maven构建项目
- 填写相应的组织名和骨架名
- 配置Maven环境
- Maven项目创建成功
- 项目目录
- <!-- pom.xml文件的内容 --> <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.xlauncher</groupId> <artifactId>driverDemo</artifactId> <version>1.0-SNAPSHOT</version> <name>driverDemo</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <!--在这里添加依赖--> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> <build> <pluginManagement> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.0.0</version> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.20.1</version> </plugin> <plugin> <artifactId>maven-jar-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
-
- 在pom.xml文件中添加下面代码,等待其从中央仓库下载,如果下载速度过慢,配置阿里镜像源,点击查看详情。
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.45.0</version>
</dependency>
<!--并将Junit的版本改成4.12-->
- 创建一个类【下面的例子是Chrome】
- package com.webdriver; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; /** * @author YangDengcheng * @time 18-3-13 下午3:47 */ public class TestBaidu { public static void main(String[] args) { // 加载相应的驱动,第二个参数是驱动路径 System.setProperty("webdriver.chrome.driver","/home/ydc/Downloads/chromedriver"); WebDriver driver = new ChromeDriver(); // 放大窗口 driver.manage().window().maximize(); // 访问www.baidu.com driver.get("https://www.baidu.com"); // 获取输入框,并输入hello Test driver.findElement(By.id("kw")).sendKeys("hello Test"); // 点击”搜索“按钮 driver.findElement(By.id("su")).click(); try { Thread.sleep(3000); }catch (InterruptedException i){ i.printStackTrace(); }; // 关闭浏览器窗口 driver.close(); } }
三、Webdriver API学习
3.1 从定位元素开始
Webdriver提供了八种元素定位方式,在JAVA中的定位方法如下:
- id ----findElement(By.id())
- name ----findElement(By.name())
- class name ----findElement(By.className())
- tag name ----findElement(By.tagName))
- link text ----findElement(By.linkText())
- partial link text ----findElement(By.partialLinkText())
- xpath ----findElement(By.xpath())
- css selector ----findElement(By.cssSeletor())
id定位、name定位、class定位都是通过他们的属性值来的
link定位:
专门用来定位文本
<a class="mnav" name="tj_trnews" href="http://news.baidu.com">新闻</a>
对应的link定位 findElement(By.linkText("新闻"))
partial link定位
parial link定位是对link定位的一个补充,有些文本链接会比较长,这个时候我们可以取文本链接的一部分定位,只要这一部分信息可以唯一地标识这个链接。
<a class="mnav" name="tj_trnews" href="http://news.baidu.com">这是一个很长很长的文本链接</a>
对应的partial link定位findElement(By.partialLinkText("一个很长的"))或findElement(By.partialLinkText("文本链接"))
xpath定位:
最简单的找到元素的位置的方法就是打开FireBug,打开火狐浏览器审查元素,查找xpath一项,复制下来即可
css定位:
- <span class="sp"> <input id="abc" name="def" class="ghi" type="text" maxlength='100' /> </span> 通过class属性定位:findElement(By.cssSelector(".ghi")); 通过id属性定位:findElement(By.cssSelector("#abc")); 通过标签名定位:findElement(By.cssSelector("input")); 通过父子关系定位:findElement(By.cssSelector("span > input")); 通过属性定位:findElement(By.cssSelector("input[maxlength='100']"));
3.2 控制浏览器大小
3.2.1 控制浏览器窗口大小
driver.manage().window().setSize(new Dimension(400,500));
3.2.2 控制浏览器后退、前进
//后退
driver.navigate().back();
//前进
driver.navigate().forward();
//刷新
driver.navigate().refresh();
3.3 简单的元素操作
- clear()--------清除文本
- sendKeys(value)--------模拟按键输入
- click()--------单击元素
- submit()--------提交表单
- getSize()--------返回元素的尺寸
- getText()--------获取元素的文本
- getAttribute(name)--------获取属性值
- isDisplayed()--------设置该元素是否用户可见
3.4 鼠标事件
Actions类提供了鼠标操作的常用方法
- contextClick()--------右击
- clickAndHold()--------鼠标点击并控制
- doubleClick()--------双击
- dragAndDrop()--------拖动
- release()--------释放鼠标
- perform()--------执行所有Actions存储的行为
E.g 鼠标右击操作
1.导入ActionChains类
2.引入Actions类,并将浏览器驱动driver作为参数传进去,actions(driver)
3.contextCLick()方法用于模拟鼠标右键操作,在调用时需要指定元素定位。
4.perform()执行所有ActionChains中存储的行为,可以理解成是对整个操作的提交动作。
action.contextClick(driver.findElement(By
.className("xxx"))).perform();
E.g 鼠标悬停操作
action.clickAndHold(driver.findElement(By.linkText("设置"))).perform();
E.g 鼠标双击操作
action.doubleClick(driver.findElement(By.className(""))).perform();
E.g 鼠标拖放操作
dragAndDrop(source,target)在源元素上按下鼠标左键,然后移动到目标元素上释放。
source:鼠标拖动的源元素。
target:鼠标释放的目标元素。
WebElement source = driver.findElement(By.className("element"));
WebElement target = driver.findElement(By.className("element"));
action.dragAndDrop(source,target).perform();
E.g 释放鼠标
action.release().perform();
3.5 键盘事件
使用键盘按键方法前需要先导入keys类。 下面为常用的键盘操作:
- sendKeys(Keys.BACK_SPACE)--------删除键(BackSpace)
- sendKeys(Keys.SPACE)--------空格键(Space)
- sendKeys(Keys.TAB)--------制表键(Tab)
- sendKeys(Keys.ESCAPE)--------回退键(Esc)
- sendKeys(Keys.ENTER)--------回车键(Enter)
- sendKeys(Keys.CONTROL,'a')--------全选(Ctrl+A)
- sendKeys(Keys.CONTROL,'c')--------复制(Ctrl+C)
- sendKeys(Keys.CONTROL,'x')--------剪切(Ctrl+X)
- sendKeys(Keys.CONTROL,'v')-------- 粘贴(Ctrl+V)
- sendKeys(Keys.F1-F12)--------键盘F1-F2
E.g Chrome浏览器在百度搜索
package com.webdriver;
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;
/**
* @author YangDengcheng
* @time 18-3-14 下午4:21
*/
public class TestKey {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver","/home/ydc/Downloads/chromedriver");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("http://www.baidu.com");
WebElement input = driver.findElement(By.id("kw"));
// 在搜索框输入seleniumm
input.sendKeys("seleniumm");
// 删除多余的m
input.sendKeys(Keys.BACK_SPACE);
// 输入空格
input.sendKeys(Keys.SPACE);
input.sendKeys("教程");
// 全选
input.sendKeys(Keys.CONTROL,"a");
// 剪切
input.sendKeys(Keys.CONTROL,"x");
// 粘贴
input.sendKeys(Keys.CONTROL,"v");
// 输入回车查询
input.sendKeys(Keys.ENTER);
try {
Thread.sleep(3000);
}catch (InterruptedException i){
i.printStackTrace();
};
// 浏览器关闭
driver.close();
}
}
3.6 获得验证信息
- getTitle()--------用于获得当前页面的title
- getCurrentUrl()--------用于获得当前页面URL
3.7 设置元素等待
3.7.1 timeouts方法
Webdriver提供了几种方法来等待元素。
通过driver.manage().timeouts()进行调用
- implicityWait:识别对象时的超时时间。过了这个时间如果对象还没找到的话就会抛出NoSuchElement异常。
- setScriptTimeout:异步脚本的超时时间。WebDriver可以异步执行脚本,这个是设置异步执行脚本脚本返回结果的超时时间。
- pageLoadTimeout:页面加载时的超时时间。因为WebDriver会等页面加载完毕再进行后面的操作,所以如果页面超过设置时间依然没有加载完成,那么WebDriver就会抛出异常。
3.7.2 sleep休眠方法
Thread.sleep()方法。当执行到sleep()方法时会固定的休眠所设置的时长,单位为毫秒;然后再继续执行。
注意,这里的Thread.sleep()方法不能直接使用,必须加上异常处理。
package com.webdriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.concurrent.TimeUnit;
/**
* @author YangDengcheng
* @time 18-3-15 上午10:04
*/
public class TestTimeout {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver","/home/ydc/Downloads/chromedriver");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
// 页面加载超时时间为5S
driver.manage().timeouts().pageLoadTimeout(5, TimeUnit.SECONDS);
driver.get("http://www.baidu.com");
// 定位对象的时间设置为5秒,如果没有定位到抛异常
driver.manage().timeouts().implicitlyWait(5,TimeUnit.SECONDS);
driver.findElement(By.id("kww")).sendKeys("test Selenium");
// 异步脚本的超时时间为5秒
driver.manage().timeouts().setScriptTimeout(5,TimeUnit.SECONDS);
//Thread.sleep() 必须包括异常处理
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 浏览器关闭
driver.close();
}
}
3.8 定位一组元素
定位一组元素的方法与定位单个元素的方法类似,唯一的区别是在单词element后面多了一个“s”表示复数。定位一组元素一般用于以下场景:
- 批量操作元素,例如勾选页面上所有的复选框
- 先获取一组元素,再从这组对象中过滤出需要操作的元素。例如定位出页面上所有的checkbox,然后选择其中的一个进行操作。
3.9 对于select下拉框的操作
WebDriver为下拉框设置了一些方法,首先需要选中元素。即上面描述的通过ID、xpath来获取元素。然后我们使用WebDriver中Select这个类和它提供的方法来操作select。
- selectByIndex(int x) 根据索引改变下拉框状态
- selectByValue(String value) 根据value值改变下拉框状态
- selectByVisibleText(String textValue) 根据可见文本改变下拉框的状态
Select selectItem = new Select(WebElement element);
E.g
// 有一个id为fruit的select,option的value为banana、apple、orange,其中这些文本内容为Banana、Apple、Orange。
Webelement element = driver.findElement(By.id("fruit");
Select fruit = new Select(element);
// 获得索引为0的元素
fruit.selectByIndex(0);
// 获取value属性为apple的元素
fruit.selectByValue("apple");
// 获取课件文本为Orange的元素
fruit.selectByVisibleText("Orange");
3.10 模拟鼠标停留显现悬浮的窗体
这里我为大家以淘宝为例子,会用到之前的知识。同时也会用到Webdriver为大家提供的一个模拟鼠标键盘的类(Actions)。
package com.webdriver;
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.interactions.Action;
import org.openqa.selenium.interactions.Actions;
/**
* @author YangDengcheng
* @time 18-3-13 下午3:47
*/
public class TestTaobao {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver","/home/ydc/Downloads/chromedriver");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
// 第一步:浏览器地址栏输入淘宝网址
driver.get("https://www.taobao.com");
// 第二步:基于xpath获取元素
WebElement element = driver.findElement(By.xpath("/html/body/div[4]/div[1]/div[1]/div[1]/div/ul/li[1]"));
// 第三步【关键】:new一个Actions的对象
Actions actions = new Actions(driver);
// 第四步:鼠标移动到【女装/男装/内衣】这个元素上面,将模拟的事件构建成一个操作,但并没有释放。
Action mouseOverItem = actions.moveToElement(element).build();
// 第五步:调用perform()方法释放之前的操作。
mouseOverItem.perform();
try {
Thread.sleep(3000);
}catch (InterruptedException i){
i.printStackTrace();
}
driver.close();
}
}
3.11 浏览器多窗口切换
在浏览器有多个窗口的时候,想切换到指定的窗口,就需要根据windows窗口handle来切换,每一个窗口都有一个handle的标识。
模拟一个这样的多窗口切换,以百度为例,输入百度的地址,点击其导航栏的超链接,显示多个窗口,并且可以随意切换。
package com.webdriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.Set;
/**
* @author YangDengcheng
* @time 18-3-13 下午3:47
*/
public class TestHandle {
public static boolean switchWindow(String windowTitle,WebDriver webDriver){
boolean flag = false;
try {
// 获取当前窗口的handle
String currentHandle = webDriver.getWindowHandle();
// 将页面上所有的handle放到一个set集合中
Set<String> setHandles = webDriver.getWindowHandles();
// 循环遍历这个集合中的元素
for(String handle:setHandles){
// 如果和当前的窗口的handle一样,跳出本次循环,继续下次循环
if (handle.equals(currentHandle)){
continue;
}else{
// 如果不一样就切换到那个handle,对比这个页面中的title是否包含传入的windowTitle,如果是就返回true,跳出循环
webDriver.switchTo().window(handle);
if (webDriver.getTitle().contains(windowTitle)){
flag = true;
System.out.println("Switch to window:" + windowTitle + "successfully!");
break;
}else {
continue;
}
}
}
}catch (Exception e){
System.out.println("Window:" + windowTitle + "can not found!");
flag = false;
}
return flag;
}
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver","/home/ydc/Downloads/chromedriver");
WebDriver driver = new ChromeDriver();
// 登录淘宝页面
driver.get("https://www.taobao.com");
// 点击天猫超链接
WebElement elementByTmall = driver.findElement(By.xpath("/html/body/div[3]/div/ul[1]/li[1]/a"));
// 点击聚划算超链接
WebElement elementByJu = driver.findElement(By.xpath("/html/body/div[3]/div/ul[1]/li[2]/a"));
elementByTmall.click();
elementByJu.click();
// 选取对应的handle
TestHandle.switchWindow("天猫tmall.com--理想生活上天猫",driver);
// 获取输入框并且输入”test“
driver.findElement(By.id("mq")).sendKeys("test");
// 点击”搜索“按钮
driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/div/div/div[2]/form/fieldset/div/button")).click();
try {
Thread.sleep(3000);
}catch (InterruptedException i){
i.printStackTrace();
}
// 浏览器关闭
driver.quit();
}
}
四、第一个测试代码
4.1 测试代码
使用Java基于Webdriver的自动化模拟浏览器操作已经了解,下面附上一个完成的测试代码。这里我们基于Webdriver+Junit来进行功能测试。
package com.webdriver;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
/**
* @author YangDengcheng
* @time 18-5-9 上午10:28
*/
public class TestWebdriver {
WebDriver webDriver;
// 在执行测试代码前需要执行的操作
@Before
public void setUp() throws Exception{
// 加载浏览器驱动
System.setProperty("webdriver.chrome.driver","/home/ydc/Downloads/chromedriver");
webDriver = new ChromeDriver();
}
// 测试代码
@Test
public void test(){
// 网站的网址
webDriver.get("https://8.16.0.71:30403");
// 找到id为login_username的元素,并输入“admin”
webDriver.findElement(By.id("login_username")).sendKeys("admin");
// 找到id为login_password的元素,并输入“Harbor12345”
webDriver.findElement(By.id("login_password")).sendKeys("Harbor12345");
// 通过xpath找到按钮的位置并点击
webDriver.findElement(By.xpath("/html/body/harbor-app/harbor-shell/clr-main-container/div/div/sign-in/div/form/div[1]/button")).click();
// 断言该页面的title是否是“Harbor”
Assert.assertEquals("Title check failed","Harbor",webDriver.getTitle());
}
// 测试代码执行后执行的操作
@After
public void setDown() throws Exception{
Thread.sleep(5000);
// 关闭浏览器
webDriver.close();
}
}
4.2 运行测试查看结果
-
运行测试代码
-
查看测试结果
几个“坑”请小心
- 由于各个浏览器更新很迅速,有的时候会因为版本问题头疼,最重要的就是浏览器驱动的版本和Selenium Webdriver第三方提供的依赖包和浏览器版本不兼容,这时候就需要保证两个版本保持兼容,要么下载最新的Selenium Webdriver的依赖,要么就在本地安装低版本的浏览器。下面为大家提供一下chrome浏览器和Selenium Webdriver依赖包的版本(更新至.v2.37):
Chrome-Driver Version | 支持的Chrome版本 |
---|---|
v2.37 | v64-66 |
v2.36 | v63-65 |
v2.35 | v62-64 |
v2.34 | v61-63 |
v2.33 | v60-62 |
v2.32 | v59-61 |
v2.31 | v58-60 |
v2.30 | v58-60 |
v2.29 | v56-58 |
v2.28 | v55-57 |
v2.27 | v54-56 |
v2.26 | v53-55 |
v2.25 | v53-55 |
v2.24 | v52-54 |
v2.23 | v51-53 |
v2.22 | v49-52 |
v2.21 | v46-50 |
v2.20 | v43-48 |
v2.19 | v43-47 |
v2.18 | v43-46 |
v2.17 | v42-43 |
v2.15 | v40-43 |
v2.14 | v39-42 |
v2.13 | v38-41 |
v2.12 | v36-40 |
v2.11 | v36-40 |
v2.10 | v33-36 |
v2.9 | v31-34 |
v2.8 | v30-33 |
v2.7 | v30-33 |
v2.6 | v29-32 |
v2.5 | v29-32 |
v2.4 | v29-32 |
- 如果使用的是默认的火狐浏览器时,需要对应好Selenium Webdriver的版本和火狐浏览器的版本,当出现以下报错时是由于火狐浏览器版本过高或者Selenium Webdriver的版本过低。
org.openqa.selenium.firefox.NotConnectedException: Unable to connect to host 127.0.0.1 on port 7055 after 45000 ms
附上Ubuntu安装低版本火狐的链接