前言
这些是过去学习和工作中积累的个人总结,不过可能会存在一些主观臆断,如果有说错的地方,请指出来哦!
回答
在Selenium中提供了四种等待方式,分别是强制等待,隐式等待,显示等待以及FluentWait等待。
强制等待
-
原理:强制等待,线程休眠一定时间
-
优缺点
- 优点:简单
- 缺点:不能准确把握等待的时间(有点浪费时间),影响执行速度
-
使用方法:Thread.sleep(x),等待x毫秒后,进行下一步操作
-
使用场景:脚本调试,脚本编写
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class ElementWait {
private static WebDriver driver;
// 前置条件 driver实例化
@BeforeAll
static void setUP() {
System.setProperty("webdriver.chrome.driver", "/Users/wangtao/TestTools/Java/SeleniumCase/src/main/resources/ChromeDriver/chromedriver");
driver = new ChromeDriver();
}
// 后置操作 浏览器退出
@AfterAll
static void tearDown() {
driver.quit();
}
//测试步骤
@Test
public void locatorByID() throws InterruptedException {
// 打开浏览器
driver.get("https://www.baidu.com/");
// 窗口最大化
driver.manage().window().maximize();
// 根据partialLinkText定位的方式,定位到新闻元素,并且点击
driver.findElement(By.id("kw")).sendKeys("测试论坛");
// 强制等待2000毫秒(2秒)
Thread.sleep(2000);
}
}
隐式等待
-
原理:设置一个等待时间,轮询查找(默认0.5秒)元素是否出现,如果没有出现就抛出异常
-
优缺点
- 优点:只需要在整个driver生命周期中设置一次即可
- 缺点:如果找不到元素,就不管了。只关注元素能不能找到,不关注元素能否点击或者进行其他的交互。相对而言,效率会受到影响。必须等到页面加载策略实现以后,才会开始执行
-
使用方法:driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
-
使用场景:可解决找不到元素问题,但无法解决交互问题
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.time.Duration;
public class ElementWait {
private static WebDriver driver;
// 前置条件 driver实例化
@BeforeAll
static void setUP() {
System.setProperty("webdriver.chrome.driver", "/Users/wangtao/TestTools/Java/SeleniumCase/src/main/resources/ChromeDriver/chromedriver");
driver = new ChromeDriver();
}
// 后置操作 浏览器退出
@AfterAll
static void tearDown() {
driver.quit();
}
//测试步骤
@Test
public void locatorByID() throws InterruptedException {
// 打开浏览器
driver.get("https://vip.ceshiren.com//");
// 窗口最大化
driver.manage().window().maximize();
driver.findElement(By.xpath("//*[text()='个人中心']"));
}
}
显示等待
-
原理:在最长等待时间内,是否满足结束条件
-
优缺点
- 优点:更精确的等待,脚本更灵活以及稳定性更好
- 缺点:增加代码复杂性以及依赖性
-
使用方法:WebDriverWait(driver实例, 最长等待时间).until(结束条件);
-
使用场景:解决特定条件下的等待问题,比如点击等交互性行为
-
常见 expected_conditions
类型 | 示例方法 | 说明 |
---|---|---|
element | elementToBeClickable() | |
visibilityOfElementLocated() | 针对于元素,比如判断元素是否可以点击,或者元素是否可见 | |
url | urlContains() | 针对于url |
title | titleIs() | 针对于标题 |
frame | frameToBeAvailableAndSwitchToIt() | 针对于frame |
alert | alertIsPresent() | 针对于弹窗 |
具体可详见:ExpectedConditions说明 |
- 定制等待条件
官方的 ExpectedConditions 不可能覆盖所有场景,故需要定制等待条件且定制封装条件会更加灵活、可控。
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
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.time.Duration;
public class ElementLocate {
private static WebDriver driver;
// 前置条件 driver实例化
@BeforeAll
static void setUP() {
System.setProperty("webdriver.chrome.driver", "/Users/wangtao/TestTools/Java/SeleniumCase/src/main/resources/ChromeDriver/chromedriver");
driver = new ChromeDriver();
}
// 后置操作 浏览器退出
@AfterAll
static void tearDown() {
driver.quit();
}
//测试步骤
@Test
public void locatorByID() {
// 打开网址
driver.get("https://vip.ceshiren.com/#/ui_study");
// 窗口最大化
driver.manage().window().maximize();
// 显示等待,等待按钮success_btn,可点击的时候操作
WebElement resElement = new WebDriverWait(driver,
Duration.ofSeconds(10))
.until(ExpectedConditions.elementToBeClickable(
By.id("success_btn")));
resElement.click();
}
}
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
public class TeatCase {
public static WebDriver webDriver;
public static WebDriverWait wait;
// 前置条件 driver实例化
@BeforeAll
static void setUP() {
System.setProperty("webdriver.chrome.driver", "/Users/wangtao/TestTools/Java/SeleniumJava/SeleniumStudyL1/src/main/resources/ChromeDriver/chromedriver");
webDriver = new ChromeDriver();
wait = new WebDriverWait(webDriver, Duration.ofSeconds(1000));
}
// 后置操作 浏览器退出
@AfterAll
static void tearDown() {
webDriver.quit();
}
//测试步骤
@Test
public void elementOperate() throws InterruptedException {
// 打开页面
webDriver.get("https://vip.ceshiren.com/#/ui_study");
Thread.sleep(1000);
//显示等待,定制显示等待的条件
wait.until((driver) -> {
driver.findElement(By.xpath("//*[text()='点击两次响应']")).click();
return driver.findElement(By.xpath("//*[text()='该弹框点击两次后才会弹出']"));
});
}
}
FluentWait等待
-
什么是FluentWait
- 与显式等待近似
- 设定超时时间
- 设定轮询频率
- 忽略特定类型的异常
-
使用场景
-
更深层次的定制
- 轮询频率
- 忽略指定异常
-
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
public class TeatCase {
public static WebDriver webDriver;
// 前置条件 driver实例化
@BeforeAll
static void setUP() {
System.setProperty("webdriver.chrome.driver", "/Users/wangtao/TestTools/Java/SeleniumJava/SeleniumStudyL1/src/main/resources/ChromeDriver/chromedriver");
webDriver = new ChromeDriver();
}
// 后置操作 浏览器退出
@AfterAll
static void tearDown() {
webDriver.quit();
}
//测试步骤
@Test
public void elementOperate() throws InterruptedException {
// 打开网址
webDriver.get("https://vip.ceshiren.com/#/ui_study");
//FluentWait等待条件设置(超时值,轮询频率,忽略异常)
Wait<WebDriver> wait1=new FluentWait<WebDriver>(webDriver)
//设置等待评估条件为真的时间 ---超时值
.withTimeout(Duration.ofSeconds(30))
////设置评估条件的频率 ---轮询频率
.pollingEvery(Duration.ofSeconds(5))
// 忽略特定类型的异常
.ignoring(NoSuchElementException.class);
// 设置FluentWait结束条件
WebElement ele = wait1.until((webDriver)->
webDriver.findElement(By.id("warning_btn")));
ele.click();
}
}
总结
在编写脚本的调试阶段,通常会使用强制等待来进行。一旦脚本调试完成,就可以根据元素的具体情况选择切换成隐式等待或者是显示等待。对于FluentWait等待,通常情况下使用得比较少,只有在需要进行定制的情况下才会使用。