WebDriver API 是一组允许程序控制和自动化Web浏览器的接口,它是Selenium框架的一部分。Selenium 是一个广泛使用的开源自动化测试工具,用于Web应用程序的自动化测试。WebDriver API 提供了与浏览器进行交互的能力,支持多种浏览器,包括Chrome、Firefox、Edge、Safari等。
本文会对其常用 API 进行详细的介绍。
目录
[一、通过 WebDriver,WebElement 接口与浏览器交互](#一、通过 WebDriver,WebElement 接口与浏览器交互)
[二、查找(定位)页面元素:findElement 和 findElements](#二、查找(定位)页面元素:findElement 和 findElements)
[1. 绝对路径](#1. 绝对路径)
[2. 相对路径](#2. 相对路径)
[1. send_keys](#1. send_keys)
[2. click](#2. click)
[3. submit](#3. submit)
[4. clear](#4. clear)
[5. text](#5. text)
[1. sleep 等待](#1. sleep 等待)
[2. 智能等待](#2. 智能等待)
[2.1 隐式等待](#2.1 隐式等待)
[2.2 显式等待](#2.2 显式等待)
[2.3 等待常见报错](#2.3 等待常见报错)
一、通过 WebDriver,WebElement 接口与浏览器交互
WebDriver接口是整个API的核心,所有与浏览器的交互都是通过该接口实现的。具体的浏览器驱动程序(如ChromeDriver
、FirefoxDriver
等)都是实现了该接口的类。
WebElement接口表示HTML文档中的一个元素。通过WebElement,可以执行各种操作,如点击、输入文本、获取元素属性等
我们通过一个具体的例子来感受一下 WebDriver 的大概功能。
java
package org.example;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class WebDriverExample {
public static void main(String[] args) {
// 设置ChromeDriver的路径
System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
// 初始化WebDriver
WebDriver driver = new ChromeDriver();
// 打开指定的URL
driver.get("https://www.example.com");
// 查找元素
WebElement searchBox = driver.findElement(By.name("q"));
// 输入查询内容并提交
searchBox.sendKeys("Selenium WebDriver");
searchBox.submit();
// 获取并打印当前页面的标题
String title = driver.getTitle();
System.out.println("Page title is: " + title);
// 关闭浏览器
driver.quit();
}
}
以上代码展示了如何启动一个Chrome浏览器,打开一个指定的URL,查找搜索框元素,输入查询内容并提交,最后获取并打印页面标题,最后关闭浏览器。
导航和操作浏览器
笔者直接将相关导航和操作浏览器的方法写入示例中,请看示例:
java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class BrowserOperations {
public static void main(String[] args) {
// 设置ChromeDriver的路径
System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
// 初始化WebDriver
WebDriver driver = new ChromeDriver();
// 打开百度首页
driver.get("https://www.baidu.com");
// 获取当前页面的标题
String title = driver.getTitle();
System.out.println("Page title is: " + title);
// 获取当前页面的URL
String currentUrl = driver.getCurrentUrl();
System.out.println("Current URL is: " + currentUrl);
// 打开另一个页面
driver.get("https://www.google.com");
// 获取新页面的标题
String newTitle = driver.getTitle();
System.out.println("New page title is: " + newTitle);
// 关闭当前窗口
driver.close();
// 重新初始化WebDriver并打开百度首页(重新创建一个新的ChromeDriver实例并打开百度首页。)
driver = new ChromeDriver();
driver.get("https://www.baidu.com");
// 退出浏览器,关闭所有相关窗口
driver.quit();
}
}
二、查找(定位)页面元素:findElement 和 findElements
在Selenium WebDriver中,findElement
和 findElements
是用于查找页面元素的两个主要方法。它们可以根据不同的定位策略来查找单个元素或多个元素。
| | findElement | findElements |
| 作用 | 查找并返回页面上第一个匹配指定定位策略的元素 | 查找并返回页面上所有匹配指定定位策略的元素 |
| 返回值 | 返回一个 **WebElement
**对象 | 返回一个包含所有匹配元素的 List<WebElement>
对象 如果没有找到匹配的元素,返回一个空列表 |
| 异常处理 | 如果找不到匹配的元素,会抛出 NoSuchElementException
异常 | 即使找不到任何匹配的元素,也不会抛出异常,只会返回一个空的 List
|
示例 | java WebElement element = driver.findElement(By.id("elementId")); |
java List<WebElement> elements = driver.findElements(By.className("className")); |
---|
常用的定位策略
Selenium 提供了多种定位策略来查找元素:
| 定位策略 | 方法 | 说明 | 示例 |
| id | java By.id(String id)
| 适用于元素有唯一的 id
属性 | java driver.findElement(By.id("elementId"));
|
| name | java By.name(String name)
| 适用于元素有唯一的 name
属性 | java driver.findElement(By.name("elementName"));
|
| className | java By.className(String className)
| 适用于元素有特定的 class
属性 | java driver.findElement(By.className("className"));
|
| tagName | java By.tagName(String tagName)
| 适用于查找特定标签名的元素,如 <input>
、<button>
等 | java driver.findElement(By.tagName("div"));
|
| LinkText | java By.linkText(String linkText)
| 适用于查找链接文本完全匹配的 <a>
标签 | java driver.findElement(By.linkText("Example Link"));
|
| partialLinkText | java By.partialLinkText(String linkText)
| 适用于查找链接文本部分匹配的 <a>
标签 | java driver.findElement(By.partialLinkText("Example"));
|
| cssSelector | java By.cssSelector(String cssSelector)
| 适用于使用CSS选择器查找元素 | java driver.findElement(By.cssSelector(".className #id"));
|
XPath | java By.xpath(String xpath) |
适用于使用XPath表达式查找元素 | java driver.findElement(By.xpath("//div[@id='elementId']")); |
---|
关于XPath的基本语法
XPath(XML Path Language)是一种在XML文档中查找元素的语言。虽然它主要用于XML文档,但在Web开发中,我们也经常使用XPath在HTML文档中定位网页元素。XPath非常强大,允许我们通过各种复杂的规则查找元素,这些规则比简单的ID或类名要灵活得多。
XPath提供了很多功能和表达式来定位元素。以下是一些常见的XPath语法和用法:
1. 绝对路径
绝对路径从根节点开始,一直指定到目标元素。绝对路径以单斜杠 /
开始。
XML
/html/body/div[1]/div[2]/a
这个XPath表示从HTML根节点开始,依次经过body、div等节点,最终找到一个a标签。
2. 相对路径
相对路径从当前节点开始,不以单斜杠 /
开头。相对路径更常用,因为它更灵活,不依赖于页面的整体结构。
相对路径主要使用双斜杠 //
或单斜杠 /
开始:
//
: 从当前节点的所有后代节点中查找匹配的元素,不限于直接子节点。/
: 从当前节点的直接子节点中查找匹配的元素。
相对路径常见用法
| | xpath | 说明 | 示例 | 说明 |
| 基于标签名称查找 | XML //tagName
| 查找所有指定标签的元素 | XML //div
| 查找所有的 div
元素 |
| 基于属性查找 | XML //tagName[@attribute='value']
| 根据属性值查找元素 | XML //input[@id='username']
| 查找 id
属性为 username
的 input
元素 |
| 基于部分属性值查找 contains | XML //tagName[contains(@attribute, 'partialValue')]
| 查找属性值中包含指定部分内容的元素。 | XML //a[contains(@href, 'login')]
| 查找 href
属性中包含 login
的所有 a
元素 |
| 基于文本内容查找 text() | XML //tagName[text()='textValue']
| 根据元素的文本内容查找元素 | XML //button[text()='Submit']
| 查找文本内容为 Submit
的 button
元素。 |
| 基于部分文本内容的查找 | XML //tagName[contains(text(), 'partialText')]
| 这查找文本内容中包含指定部分内容的元素 | XML //p[contains(text(), 'Welcome')]
| 查找文本内容中包含 Welcome
的所有 p
元素 |
| 组合条件查找 | XML //tagName[@attribute='value' and text()='textValue']
| 组合多个条件进行查找 | XML //input[@type='text' and @name='username']
| 查找 type
属性为 text
且 name
属性为 username
的 input
元素 |
| 查找父节点 | XML //tagName/..
| 查找元素的父节点 | XML //input[@id='username']/..
| 查找 id
为 username
的 input
元素的父节点 |
查找子节点 | XML //parentTagName/childTagName |
查找直接子节点 | XML //div/span |
查找所有 div 元素的直接 span 子节点。 |
---|
补充:
基于通配符
- 匹配任何标签
使用 *
作为标签名,可以匹配任何标签。这在不知道确切标签名的情况下非常有用。
XML
//*[text()='Submit']
这个XPath表达式匹配所有文本内容为 Submit
的元素,不论它们的标签名是什么。
- 匹配部分属性值
使用 contains()
函数可以匹配部分属性值,特别适用于那些属性值会动态变化的情况。
XML
//input[contains(@id, 'user')]
这个XPath表达式匹配所有 id
属性中包含 user
的 input
元素。
- 匹配部分文本内容
同样可以使用 contains()
函数来匹配部分文本内容。
XML
//div[contains(text(), 'Welcome')]
这个XPath表达式匹配所有文本内容中包含 Welcome
的 div
元素。
- 匹配属性名
使用 @*
可以匹配任何属性名。
XML
//*[@*='value']
这个XPath表达式匹配所有具有值为 value
的任意属性的元素。
应用示例
假设我们有以下HTML结构:
html
<html>
<body>
<div class="container">
<h1>Welcome to My Page</h1>
<form id="loginForm">
<input type="text" name="username" id="username" />
<input type="password" name="password" />
<button type="submit">Login</button>
</form>
</div>
</body>
</html>
我们可以使用以下XPath表达式查找元素:
- 查找
id
为loginForm
的form
元素:
html
//form[@id='loginForm']
- 查找
name
属性为username
的input
元素:
html
//input[@name='username']
- 查找
type
属性为submit
的button
元素:
html
//button[@type='submit']
- 查找文本内容为
Welcome to My Page
的h1
元素:
html
//h1[text()='Welcome to My Page']
- 查找所有
div
元素中的input
元素:
html
//div//input
示例代码
以下是一个使用相对路径的Java示例:
java
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class XPathRelativeExample {
public static void main(String[] args) {
// 设置ChromeDriver的路径
System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
// 初始化WebDriver
WebDriver driver = new ChromeDriver();
// 打开指定的URL
driver.get("https://www.example.com");
// 使用XPath查找元素
WebElement usernameInput = driver.findElement(By.xpath("//input[@id='username']"));
WebElement loginButton = driver.findElement(By.xpath("//button[text()='Login']"));
// 对元素进行操作
usernameInput.sendKeys("myUsername");
loginButton.click();
// 关闭浏览器
driver.quit();
}
}
三、通过WebElement接口操作页面元素
Selenium webdriver 核心之一是对页面元素的操作,前文已经通过定位策略定位到了具体的元素, 那么接下来我们可以通过使用WebElement接口,拟用户行为,如输入文本、点击按钮、提交表单等。这使得我们能够自动化地执行各种用户操作,从而进行功能测试、回归测试等。
1. send_keys
send_keys
方法用于在输入框或文本区域上模拟按键输入。
示例:
java
WebElement inputField = driver.findElement(By.name("q"));
inputField.sendKeys("Selenium WebDriver");
- 作用:向名为 "q" 的输入框输入 "Selenium WebDriver"。
2. click
click
方法用于点击页面上的元素,如按钮、链接等。
示例:
java
WebElement searchButton = driver.findElement(By.name("btnK"));
searchButton.click();
- 作用:点击名为 "btnK" 的按钮。
3. submit
示例:
java
WebElement form = driver.findElement(By.name("formName"));
form.submit();
- 作用:提交名为 "formName" 的表单。
click
和 submit
的区别
click
:用于点击按钮、链接、复选框等任何可点击的元素。submit
:专门用于提交表单,通常应用于<form>
元素或表单内的输入元素。
4. clear
clear
方法用于清除输入框或文本区域中的文本内容。
示例:
java
WebElement inputField = driver.findElement(By.name("q"));
inputField.clear();
- 作用:清空名为 "q" 的输入框中的文本内容。
5. text
text
属性用于获取元素的文本内容。
示例:
java
WebElement element = driver.findElement(By.id("message"));
String message = element.getText();
System.out.println("Message: " + message);
- 作用:获取ID为 "message" 的元素的文本内容并打印。
示例
以下是一个综合示例,展示如何使用这些方法在百度首页上进行操作:
java
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class BaiduSearchTest {
public static void main(String[] args) {
// 设置ChromeDriver的路径
System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
// 初始化WebDriver
WebDriver driver = new ChromeDriver();
// 打开百度首页
driver.get("https://www.baidu.com");
// 找到搜索输入框并输入搜索关键词
WebElement searchBox = driver.findElement(By.id("kw"));
searchBox.sendKeys("Selenium WebDriver");
// 找到搜索按钮并点击
WebElement searchButton = driver.findElement(By.id("su"));
searchButton.click();
// 找到搜索结果页面的某个元素,获取其文本内容
WebElement result = driver.findElement(By.xpath("//div[@id='content_left']//h3/a"));
String resultText = result.getText();
System.out.println("搜索结果的标题: " + resultText);
// 清空搜索输入框
searchBox.clear();
// 关闭浏览器
driver.quit();
}
}
四、添加等待
1. sleep
等待
Thread.sleep
是Java标准库中的一种强制等待方法,它会使当前线程暂停执行指定的时间(以毫秒为单位)。这种等待方式是非智能的,因为它无法根据网页加载的实际情况来调整等待时间。
示例
java
try {
Thread.sleep(3000); // 等待3秒
} catch (InterruptedException e) {
e.printStackTrace();
}
2. 智能等待
智能等待是Selenium提供的一种更灵活的等待方式,它包括隐式等待和显式等待两种类型。智能等待可以根据网页加载的实际情况动态调整等待时间,从而提高测试的稳定性和效率。
2.1 隐式等待
隐式等待是设置一个全局的等待时间,在这个时间范围内,如果WebDriver没有找到元素,它将继续等待,直到超时。隐式等待是对整个WebDriver实例生效的。
方法签名
java
driver.manage().timeouts().implicitlyWait(long time, TimeUnit unit);
参数解释
-
long time
:- 描述:等待时间的数值。
- 作用:指定WebDriver在查找元素时的最大等待时间。
- 示例:
10
表示等待10个时间单位(由第二个参数unit
指定)。
-
TimeUnit unit
:- 描述:时间单位。
- 作用:指定
time
参数的时间单位,可以是秒、毫秒、分钟等。 - 示例:
TimeUnit.SECONDS
表示时间单位为秒。
示例:
java
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
在这个示例中,WebDriver在查找元素时会等待最多10秒。如果元素在10秒内出现,WebDriver将立即继续执行。如果在10秒内没有找到元素,WebDriver将抛出 NoSuchElementException
异常。
2.2 显式等待
显式等待是等待特定条件发生。显式等待可以在代码中指定等待的条件和最长等待时间。它只对特定的元素和条件生效。
方法签名
java
WebDriverWait wait = new WebDriverWait(WebDriver driver, long timeoutInSeconds);
WebElement element = wait.until(ExpectedConditions.condition);
参数解释
-
WebDriver driver
:- 描述:WebDriver实例。
- 作用:指定用于执行显式等待的WebDriver实例。
- 示例:
driver
是已初始化的WebDriver对象。
-
long timeoutInSeconds
:- 描述:超时时间的数值,以秒为单位。
- 作用:指定等待特定条件发生的最长时间,单位为秒。
- 示例:
10
表示等待最多10秒。
-
ExpectedConditions.condition
- 描述:指定等待的条件。
- 作用:在超时时间内,WebDriver 将持续检查此条件是否成立。如果条件成立,
until
方法将立即返回;否则,它将一直等待,直到超时时间结束。 - 示例:ExpectedConditions.visibilityOfElementLocated(By.id("elementId")) 表示等待元素可见。
常用
ExpectedConditions
visibilityOfElementLocated(By locator)
: 等待元素可见。elementToBeClickable(By locator)
: 等待元素可点击。presenceOfElementLocated(By locator)
: 等待元素存在。textToBePresentInElementLocated(By locator, String text)
: 等待元素中的文本为指定值。
示例:
java
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("elementId")));
在这个示例中,显式等待会等待最多10秒,直到指定的元素通过 ExpectedConditions
条件出现。如果在10秒内条件满足,WebDriver将继续执行。如果条件在10秒内没有满足,WebDriver将抛出 TimeoutException
异常。
2.3 等待常见报错
隐式等待中的常见报错
NoSuchElementException
- 描述:WebDriver在指定的时间内未能找到元素。
- 原因:隐式等待时间过短或页面加载速度较慢导致元素未能在预期时间内出现。
- 解决方法:增加隐式等待时间,确保页面元素有足够的时间加载。
示例:
java
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS); // 设置隐式等待时间为5秒
WebElement element = driver.findElement(By.id("nonexistentElement")); // 元素不存在,将抛出NoSuchElementException
显式等待中的常见报错
1. TimeoutException
- 描述 :在++指定的时间内未能满足++等待的条件。
- 原因:条件未能在显式等待时间内得到满足,例如元素未能在指定时间内可见或可点击。
- 解决方法:增加显式等待时间,检查条件设置是否正确,确保页面元素加载或状态变化所需时间足够。
示例:
java
WebDriverWait wait = new WebDriverWait(driver, 5); // 设置显式等待时间为5秒
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("nonexistentElement"))); // 元素不可见,将抛出TimeoutException
2. NoSuchElementException
- 描述 :在等待过程中试图访问不存在的元素。
- 原因 :查找条件设置错误,导致WebDriver尝试查找不存在的元素。
- 解决方法:检查查找条件和元素定位方法是否正确。
示例:
java
WebDriverWait wait = new WebDriverWait(driver, 5);
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(By.id("nonexistentElement"))); // 元素不存在,将抛出NoSuchElementException
示例代码
java
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.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.util.concurrent.TimeUnit;
public class WaitExample {
public static void main(String[] args) {
// 设置ChromeDriver的路径
System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
// 初始化WebDriver
WebDriver driver = new ChromeDriver();
// 隐式等待示例
try {
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS); // 设置隐式等待时间为5秒
WebElement element = driver.findElement(By.id("nonexistentElement")); // 可能抛出NoSuchElementException
} catch (NoSuchElementException e) {
System.out.println("隐式等待:元素未找到 - " + e.getMessage());
}
// 显式等待示例
try {
WebDriverWait wait = new WebDriverWait(driver, 5); // 设置显式等待时间为5秒
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("nonexistentElement"))); // 可能抛出TimeoutException
} catch (TimeoutException e) {
System.out.println("显式等待:条件未满足 - " + e.getMessage());
}
// 关闭浏览器
driver.quit();
}
}