在Selenium中,“等待”在执行测试中起着重要作用。在本教程中,将了解Selenium中隐式和显式等待的各个方面和区别。
在本教程中,将了解Selenium中不同类型的等待:
- 为什么我们需要Selenium的等待?
- 隐式等待
- 显式等待
- 流畅的等待
- 隐式等待与显式等待之间的差异
为什么我们需要Selenium的等待?
大多数Web应用程序都是使用AJAX和Javascript开发的。当浏览器加载页面时,我们希望与之交互的元素可能会以不同的时间间隔加载。
这不仅使标识元素变得困难,而且如果找不到元素,它将抛出“ElementNotVisibleException”异常。使用Selenium Waits,我们可以解决这个问题。
让我们考虑一个场景,其中我们必须在测试中同时使用隐式和显式等待。假设隐式等待时间设置为20秒,显式等待时间设置为10秒。
假设我们试图找到一个具有一些“预期条件”(显式等待)的元素,如果该元素不在显式 wait(10 Seconds) 定义的时间范围内,则在抛出“ElementNotVisibleException”之前,它将使用隐式等待(20秒)定义的时间范围。
Selenium Web驱动程序等待
- 隐式等待
- 显式等待
Selenium中的隐性等待
Selenium中的隐式等待用于告诉Web驱动程序在抛出“No That Element Exception”之前等待一定的时间。一旦我们设置了时间,Web驱动程序将在抛出异常之前等待该元素。
Selenium Web Driver借用了Watir的隐式等待的概念。
在下面的示例中,我们声明了时间范围为10秒的隐式等待。这意味着如果元素没有在该时间范围内位于网页上,它将抛出异常。
要在Selenium WebDriver中声明隐式等待,执行以下操作:
隐式等待语法:
driver.manage().timeouts().implicitlyWait(TimeOut, TimeUnit.SECONDS);
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 = "" ;
// launch Chrome and redirect it to the Base URL
driver.get("http://www.itxiaonv.com/test/guru99home/" );
//Maximizes the browser window
driver.manage().window().maximize() ;
//get the actual value of the title
aTitle = driver.getTitle();
//compare the actual title with the expected title
if (aTitle.equals(eTitle)) {
System.out.println( "Test Passed") ;
} else {
System.out.println( "Test Failed" );
}
//close browser
driver.close();
}
}
在上面的示例中,
考虑以下代码:
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS) ;
隐式等待将接受两个参数,第一个参数将接受时间为整数值,第二个参数将接受以秒、分、毫秒、微秒、纳秒、天、小时等为单位的时间度量。
Selenium中的显式等待
Selenium中的显式等待用于告诉Web驱动程序在抛出“ElementNotVisibleException”异常之前等待某些条件(预期条件)或超过最大时间。在等待动态加载的Ajax元素时,它提供了比隐式等待更好的选择。
一旦我们声明显式等待,我们就必须使用“ExspectedConditions”,或者我们可以使用流畅的等待来配置我们想要检查条件的频率。这些天在实现时,我们一般都在使用 Thread.Sleep() ,不推荐使用
在下面的示例中,我们为“WebDriverWait”类创建引用等待,并使用“WebDriver”引用进行实例化,我们给出的最大时间范围为20秒。
显式等待语法:
WebDriverWait wait = new WebDriverWait(WebDriverRefrence,TimeOut);
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 = "" ;
// launch Chrome and redirect it to the Base URL
driver.get("http://www.itxiaonv.com/test/guru99home/" );
//Maximizes the browser window
driver.manage().window().maximize() ;
//get the actual value of the title
aTitle = driver.getTitle();
//compare the actual title with the expected title
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();
}
}
考虑以下代码:
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();
在此WebDriver等待示例中,等待“WebDriverWait”类或“ExspectedConditions”中定义的时间量(以最先发生的那个为准)。
上面的Java代码声明,我们正在等待网页上的“WebDriverWait”类中定义的20秒的时间范围内的元素,直到满足“ExspectedConditions”并且条件是“visibilityof ElementLocated”。
以下是Selenium显式等待中可以使用的预期条件
- alertIsPresent()
- elementSelectionStateToBe()
- elementToBeClickable()
- elementToBeSelected()
- frameToBeAvaliableAndSwitchToIt()
- invisibilityOfTheElementLocated()
- invisibilityOfElementWithText()
- presenceOfAllElementsLocatedBy()
- presenceOfElementLocated()
- textToBePresentInElement()
- textToBePresentInElementLocated()
- textToBePresentInElementValue()
- titleIs()
- titleContains()
- visibilityOf()
- visibilityOfAllElements()
- visibilityOfAllElementsLocatedBy()
- visibilityOfElementLocated()
在Selenium中流畅地等待
Selenium中的流畅等待用于定义web驱动程序等待条件的最长时间,以及在抛出“ElementNotVisibleException”异常之前我们希望检查条件的频率。它定期检查Web元素,直到找到对象或发生超时。
频率:设置具有时间框架的重复周期,以便在固定的时间间隔验证/检查条件
让我们考虑一个场景,其中元素以不同的时间间隔加载。元素可能在10秒内加载。在这种情况下,流畅的等待是理想的等待,因为这将尝试以不同的频率查找元素,直到找到它或最终计时器用完。
等待语法:
Wait wait = new FluentWait(WebDriver reference)
.withTimeout(timeout, SECONDS)
.pollingEvery(timeout, SECONDS)
.ignoring(Exception.class);
上述代码在Selenium v3.11及更高版本中已弃用。需要使用
Wait wait = new FluentWait(WebDriver reference)
.withTimeout(Duration.ofSeconds(SECONDS))
.pollingEvery(Duration.ofSeconds(SECONDS))
.ignoring(Exception.class);
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();
// launch Chrome and redirect it to the Base URL
driver.get("http://www.itxiaonv.com/test/guru99home/" );
//Maximizes the browser window
driver.manage().window().maximize() ;
//get the actual value of the title
aTitle = driver.getTitle();
//compare the actual title with the expected title
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"));
}
});
//click on the selenium link
clickseleniumlink.click();
//close~ browser
driver.close() ;
}
}
考虑以下代码:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
在上面的示例中,我们通过忽略“NoSuchElementException”声明了一个超时为30秒的流畅等待,并将频率设置为5秒。
考虑以下代码:
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"));
我们已经创建了一个新函数来标识页面上的Web元素。(例如:这里的Web元素只是网页上的Selenium链接)。
频率设置为5秒,最长时间设置为30秒。因此,这意味着它将检查元素是否位于此时间范围内,如果元素位于此时间范围内,它将执行操作,否则将抛出“ElementNotVisibleException”
隐式等待与显式等待之间的差异
以下是Selenium中隐式等待和显式等待的主要区别:
隐式等待 | 显式等待 |
---|---|
隐式等待时间应用于脚本中的所有元素 | 显式等待时间仅适用于我们预期的那些元素 |
在隐式等待中,我们不需要在要定位的元素上指定“ExspectedConditions | 在显式等待中,我们需要在要定位的元素上指定“ExspectedConditions |
建议在元素位于Selenium隐式等待中指定的时间范围内时使用 | 建议在加载元素的时间较长以及验证元素 like(visibilityOfElementLocated, elementToBeClickable,elementToBeSelected) 的属性时使用 |
结论:
隐性等待、显性等待和流畅等待是Selenium中使用的不同等待。这些等待的用法是始终不建议在以下情况下使用 Thread.Sleep() 测试我们的应用程序或构建我们的框架。