Selenium 的等待指的是在对元素进行定位或则操作之前等待指定的一段时间,什么时候开始等待以及等待时长都取决于脚本以及使用的等待的类型。
Selenium 等待的使用有以下几个场景,比如:
- 等待元素加载完成或者可见后进行定位操作
- 等待整个页面加载完成进行操作或者获取关键信息进行断言
知识点
在 waits 包下创建新的类 ExplicitWaitCommand,具体代码如下:
package cn.lanqiao.waits;
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.WebDriverWait;
import java.time.Duration;
public class ExplicitWaitCommand {
@Test
public void testExplicit() throws Exception{
// 设置 WebDriver 的路径
System.setProperty("webdriver.chrome.driver", "C:\\Users\\jingnan\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://www.lanqiao.cn");
try {
System.out.println(System.currentTimeMillis());
WebElement ele = new WebDriverWait(driver, Duration.ofSeconds(3))
.until(driver1 -> driver1.findElement(By.id("__BVID__30")));
} catch (Exception e){
e.printStackTrace();
} finally {
System.out.println(System.currentTimeMillis());
driver.quit();
}
}
}
可通过执行上述代码,通过查找一个不存在的元素以及控制台输出的时间来判断显示等待是否生效。
关于显示等待,需要注意的是:
更多的判断条件可以查看 ExpectedConditions 的源码。
- 隐式等待(Implicit Wait)
- 显示等待(Explicit Wait)
- 强制等待 Thread Sleep
隐式等待是无条件等待,它可以应用于网页上的所有的元素。也就是说我们可以指定等待一定的时间,在指定的时间内判断到元素存在,则继续执行,超过时间则会抛出异常。
隐式等待的语法格式为:
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
或者也可以通过 Duration 来设置时间:
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
上述两种表达方式实现的效果都是一样的。
在 cn.lanqiao.waits 包下创建一个新的类 ImplicitWaitCommand,具体代码如下:
package cn.lanqiao.waits; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import java.time.Duration; public class ImplicitWaitCommandTest { @Test public void testImplicit() { // 设置 WebDriver 的路径 System.setProperty("webdriver.chrome.driver", "C:\\Users\\jingnan\\chromedriver.exe"); WebDriver driver = new ChromeDriver(); driver.get("https://www.lanqiao.cn"); // 使用隐式等待,设置等待时间为 10s driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); try { // 开始时间 System.out.println(System.currentTimeMillis()); driver.findElement(By.tagName("input")).sendKeys("Selenium"); } catch (Exception e){ e.printStackTrace(); } finally { // 结束时间 System.out.println(System.currentTimeMillis()); driver.quit(); } } }
上述代码中,首先通过设置了一个隐式等待,等待时间为 10s,接着在 Try Catch 代码块中通过 Tag Name 定位一个不存在元素,通过定位操作前后打印的时间,我们可以判断在元素定位时是是否真的等待了设置的 10s 才抛出的异常。
执行上述代码,查看控制台输出的开始时间和结束时间可以确定等待了设置的 10s。
需要注意的是隐式等待适用于页面上的所有元素,当脚本执行到某个元素定位时,如果元素存在,则继续执行,如果元素不存在则会以轮询的方式判断元素是否存在,一旦在指定的时间内判断到元素存在,则继续执行,超过时间则会抛出异常。
Selenium 的显示等待指的是 driver 等待某个条件成立则继续执行,否则在超过了设置的等待时间后抛出异常。
WebDriverWait 类是 WebDriver 提供的等待方法,在设置时间内会每隔一段时间检查当前元素是否存在,如果超出设置的时间仍然检测不到元素,就会抛出异常。
WebElement foo = new WebDriverWait(driver, Duration.ofSeconds(3)) .until(driver -> driver.findElement(By.name("q")));
until 方法返回一个 Boolean 类型,判断条件真假,在 until 方法中可以进行元素查找也可以使用 ExcepctedConditions 类进行条件判断,比如:
WebElement ele = new WebDriverWait(driver, Duration.ofSeconds(3)) .until(ExpectedConditions.visibilityOfElementLocated(By.id("kkk")))
除此之外 ExpectedConditions 还包含了其他的条件,如:
- 判断当前页面的 title 是否精确等于预期:titleIs( String title)
- 判断当前页面的 title 是否包含预期字符串:titleContains( String title)
- 判断当前页面的 url 是否精确等于预期:urlToBe( String url)
- 判断当前页面的 url 是否包含预期字符串:urlContains( String fraction)
- 字符串正则表达式:urlMatches( String regex)
- ...
- 除了作用于元素等待还可以实现其他各种场景的等待,例如页面加载等!
- 更加智能的等待方式,元素在指定的时间内找到,则不会继续等待,否则抛出 TimeOutException.
- 非全局等待,可以针对不同的元素绑定不同的等待机制,推荐优先使用这一种方式.
- 除了可以等待元素的查找,还可以支持多种其他与元素相关的条件的等待场景
强制等待其实是通过线程休眠的方式来实现的,在前面的小节中也有使用过,即:
Thread.sleep(3);
通过调用 Thread 的 sleep 方法来让线程强制休眠,从而达到等待的效果,通常可以使用在元素表较多的页面上,或者比较加载时间较长的元素上,从而避免出现元素定位不到的情况。
线程休眠的等待方式使用简单,可以在任何步骤前进行使用,但是需要注意根据实际情况选择使用,否则会造成测试用例执行时间较长的情况出现。