在selenium中,Waits在执行测试中扮演重要角色。在本教程中,您将学习Selenium中“隐式”和“显式”等待的各个方面。
在Selenium中为什么需要等待?
在现在很多软件产品为了加强前端的效果,采取了大量的AJAX、Javascript 和Jquery技术,很多窗体内的数据,需要等待一会,才能加载完数据,才能出现一些元素,driver才能操作这些元素做一些事情。
还有就是我们做一些操作,本身可能也需要等待一会才有数据显示。所以在自动化脚本开发过程,合理的设置时间等待是非常必要的,可以说百分之90以上的自动化测试用例执行失败,基本上是很时间等待有关系,造成元素没有及时在界面上显示,而报no such element子类的错误
让我们假设一个场景,我们必须在测试中同时使用隐含等待和显式等待。假设隐含等待时间设置为 20 秒,显式等待时间设置为 10 秒。
假设我们正试图找到一种元素,它有一些“ExpectedConditions”(显式等),如果不在显示等待(10秒)内, 它将使用隐式定义的时间等待(20秒)之前抛出“ElementNotVisibleException”。
假设我们试图找到一个具有一些 “ExpectedConditions” (显式等待) 的元素,如果该元素不在显式等待 (10 秒) 定义的时间范围内, 它将使用隐式等待 (20 秒) 定义的时间框架,然后抛出一个 “ElementNotVisibleException”。
Selenium提供的3种等待
1. Implicit Wait(模糊/隐式等待)
Selenium Web Driver借鉴了Watir(基于网页模式的自动化功能测试工具Web application testing in ruby)中的隐式等待概念。
隐式等待,是对整个页面元素操作有效,会先设置等待时间,一直等待所有页面内容加载完成,直到超时再抛出异常。
缺点:使用隐式等待,程序会一直等到整个页面加载完成才会执行下一步操作
需要导入一下Jar包
import java.util.concurrent.TimeUnit;
语法:
driver.manage().timeouts().implicitlyWait(TimeOut, TimeUnit.SECONDS);
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS) ;
从这个命令可以看出,这个等待是针对driver的,它会应用到所有元素的等待,对整个Driver周期起作用,只需要设置一次即可。
参数
隐式等待将接受2个参数,第一个参数将接受时间作为整数值,第二个参数将接受时间度量ECONDS, MINUTES, MILISECOND, MICROSECONDS, NANOSECONDS, DAYS, HOURS等等。
在下面的例子中,我们已经声明了一个隐式等待,时间为 10 秒。这意味着,如果元素在10秒内没有出现,它将抛出异常。
package guru.test99;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;
public class AppTest {
protected WebDriver driver;
@Test
public void guru99tutorials() throws InterruptedException {
System.setProperty ("webdriver.chrome.driver",".\\chromedriver.exe" );
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS) ;
String eTitle = "Demo Guru99 Page";
String aTitle = "" ;
// 启动Chrome并将其重定向到基本URL
driver.get("http://demo.guru99.com/test/guru99home/" );
// 最大化浏览器窗口
driver.manage().window().maximize() ;
//获取标题的实际值
aTitle = driver.getTitle();
//将实际标题与预期标题进行比较
if (aTitle.equals(eTitle)){
System.out.println( "Test Passed") ;
}else {
System.out.println( "Test Failed" );
}
//关闭浏览器
driver.close();
}
}
2. Explicit Wait (显式/明确等待)
显示等待使用WebDriverWait和ExpectedCondition类完成。
显式等待用于告诉 Web driver等待某些条件 (Expected Conditions预期条件) 或超过的最长时间,然后抛出 element entnot visibleexception异常。
显式等待是一种智能的等待,但是它只能应用于等待指定的元素加载完成。显式等待提供了比隐式等待更好的选项,因为它将动态等待加载的 Ajax 元素。
一旦我们声明了显式的Wait,我们就必须使用ExpectedCondtions,或者我们可以配置使用Fluent wait检查条件的频率。现在,在实现时我们使用Thread.Sleep(),一般不建议使用。
在下面的例子中,我们正在为“WebDriverWait”类创建引用wait,并使用“WebDriver”引用实例化它,我们给出了一个20秒的最大时间框架。
语法:
WebDriverWait wait = new WebDriverWait(WebDriverRefrence,TimeOut);
WebDriverWait wait =new WebDriverWait(driver, 20)
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath( "/html/body/div[1]/i")));
package guru.test99;
import java.util.concurrent.TimeUnit;
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 org.testng.annotations.Test;
public class AppTest2 {
protected WebDriver driver;
@Test
public void guru99tutorials() throws InterruptedException {
System.setProperty ("webdriver.chrome.driver",".\\chromedriver.exe" );
driver = new ChromeDriver();
WebDriverWait wait=new WebDriverWait(driver, 20);
String eTitle = "Demo Guru99 Page";
String aTitle = "" ;
// 启动Chrome并将其重定向到基本URL
driver.get("http://demo.guru99.com/test/guru99home/" );
//最大化浏览器窗口
driver.manage().window().maximize() ;
//获取标题的实际值
aTitle = driver.getTitle();
//将实际标题与预期标题进行比较
if (aTitle.contentEquals(eTitle)){
System.out.println( "Test Passed") ;
}else {
System.out.println( "Test Failed" );
}
WebElement guru99seleniumlink;
guru99seleniumlink= wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath( "/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i")));
guru99seleniumlink.click();
}
}
以下是可以在显式等待中使用的预期条件:
- alertIsPresent()
- elementSelectionStateToBe()
- elementToBeClickable()
- elementToBeSelected()
- frameToBeAvaliableAndSwitchToIt()
- invisibilityOfTheElementLocated()
- invisibilityOfElementWithText()
- presenceOfAllElementsLocatedBy()
- presenceOfElementLocated()
- textToBePresentInElement()
- textToBePresentInElementLocated()
- textToBePresentInElementValue()
- titleIs()
- titleContains()
- visibilityOf()
- visibilityOfAllElements()
- visibilityOfAllElementsLocatedBy()
- visibilityOfElementLocated()
3.Fluent Wait (流畅等待)
流畅等待被用来告诉 Web driver等待一个条件,以及我们想在抛出 “element entnot visibleexception” 异常之前检查这个条件的频率。
频率Frequency: 设置一个最大等待实践,而且可以设置固定的时间间隔去验证/检查特定的条件。
让我们考虑一个场景,其中一个元素在不同的时间间隔加载。如果我们显式地声明等待20秒,则元素可能在20秒、10秒甚至更短的时间内加载,它将等到指定的时间才进行下一步操作或者抛出异常。在这种情况下,流畅等待是理想的等待,因为它将尝试以不同的频率查找元素,只要找到元素即可。
语法
Wait wait = new FluentWait(WebDriver reference) .withTimeout(timeout, SECONDS) .pollingEvery(timeout, SECONDS) .ignoring(Exception.class);
所谓流畅,是指可以设置轮循检查Element的频率。
package guru.test99;
import org.testng.annotations.Test;
import java.util.NoSuchElementException;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
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.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.Test;
public class AppTest3 {
protected WebDriver driver;
@Test
public void guru99tutorials() throws InterruptedException
{
System.setProperty ("webdriver.chrome.driver",".\\chromedriver.exe" );
String eTitle = "Demo Guru99 Page";
String aTitle = "" ;
driver = new ChromeDriver();
// 启动Chrome并将其重定向到基本URL
driver.get("http://demo.guru99.com/test/guru99home/" );
//最大化浏览器窗口
driver.manage().window().maximize() ;
//获取标题的实际值
aTitle = driver.getTitle();
//将实际标题与预期标题进行比较
if (aTitle.contentEquals(eTitle))
{
System.out.println( "Test Passed") ;
}
else {
System.out.println( "Test Failed" );
}
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement clickseleniumlink = wait.until(new Function<WebDriver, WebElement>(){
public WebElement apply(WebDriver driver ) {
return driver.findElement(By.xpath("/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i"));
}
});
//单击selenium链接
clickseleniumlink.click();
//关闭浏览器
driver.close() ;
}
}
解读:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
在上面的例子中,我们声明了一个流畅的等待,超时时间为30秒,并且忽略NoSuchElementException,将频率设置为5秒,也就是每隔5秒就去重新查找并验证一次,30秒内最多验证6次,否则就是验证失败。
隐式等待和显式等待的区别:
隐式等待 Implicit Wait | 显示等待 Explicit Wait |
隐式等待时间应用于脚本中的所有元素 | 显式等待时间只应用于指定等待的元素 |
我们不需要在要定位的元素上指定ExpectedConditions | 我们需要在要定位的元素上指定ExpectedConditions |
建议在元素的出现时间小于隐式等待中指定的时间范围时使用 | 建议在元素加载时间较长时使用,也可以用于验证元素的属性,如(visibilityofelementlocate, elementToBeClickable, elementtobesselected) |
总结:
隐式、显式和流畅等待是selenium中使用的不同等待。这些等待的使用完全基于在不同时间间隔加载的元素。在测试应用程序或构建框架时,通常不建议使用Thread.Sleep()。