Selenium 等待 – 隐式和显式以及语法


在 Selenium 中,“等待”在执行测试时扮演着重要的角色。在本教程中,您将学习 Selenium 中隐式等待和显式等待的各种方面及其区别。

为什么我们需要在 Selenium 中使用等待?

大多数 Web 应用程序都是使用 AjaxJavascript 开发的。当浏览器加载页面时,我们想要交互的元素可能会在不同的时间间隔加载。

这不仅使识别元素变得困难,而且如果找不到元素,它还会抛出“ElementNotVisibleException”异常。使用 Selenium 等待,我们可以解决这个问题。

让我们考虑一个场景,我们必须在测试中同时使用隐式等待和显式等待。假设隐式等待时间设置为 20 秒,显式等待时间设置为 10 秒。

假设我们正在尝试查找具有某些“ExpectedConditions”(显式等待)的元素,如果元素未在显式等待定义的时间范围(10 秒)内找到,它将使用隐式等待定义的时间范围(20 秒)才能抛出“ElementNotVisibleException”。

Selenium WebDriver 等待

  1. 隐式等待
  2. 显式等待

在本教程中,您将学习 Selenium 中不同类型的等待

Selenium 中的隐式等待

Selenium 中的隐式等待用于告诉 WebDriver 在抛出“NoSuchElementException”之前等待一定时间。默认设置为 0。一旦我们设置了时间,WebDriver 将在该时间内等待元素,然后抛出异常。

Selenium WebDriver 借鉴了 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("https://demo.guru99.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) ;

隐式等待将接受 2 个参数,第一个参数将接受整数时间值,第二个参数将接受以秒、分钟、毫秒、微秒、纳秒、天、小时等为单位的时间测量。

Selenium 中的显式等待

Selenium 中的显式等待用于告诉 WebDriver 等待某些条件(预期条件)或最大时间超出,然后抛出“ElementNotVisibleException”异常。这是一种智能的等待方式,但只能应用于指定的元素。它比隐式等待提供了更好的选择,因为它会等待动态加载的 Ajax 元素。

一旦我们声明了显式等待,我们就必须使用“ExpectedConditions”,或者我们可以配置我们希望多久检查一次条件,使用Fluent Wait。如今,在实现时,我们通常使用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("https://demo.guru99.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”类中定义的时间量,或者等待“ExpectedConditions”的发生,以先发生者为准。

上述Java代码表明,我们正在等待网页上“WebDriverWait”类中定义的 20 秒时间范围内的元素,直到满足“ExpectedConditions”,并且条件是“visibilityofElementLocated”。

以下是可以在 Selenium 显式等待中使用的预期条件

  1. alertIsPresent()
  2. elementSelectionStateToBe()
  3. elementToBeClickable()
  4. elementToBeSelected()
  5. frameToBeAvaliableAndSwitchToIt()
  6. invisibilityOfTheElementLocated()
  7. invisibilityOfElementWithText()
  8. presenceOfAllElementsLocatedBy()
  9. presenceOfElementLocated()
  10. textToBePresentInElement()
  11. textToBePresentInElementLocated()
  12. textToBePresentInElementValue()
  13. titleIs()
  14. titleContains()
  15. visibilityOf()
  16. visibilityOfAllElements()
  17. visibilityOfAllElementsLocatedBy()
  18. visibilityOfElementLocated()

Selenium 中的流畅等待

Selenium 中的 Fluent Wait 用于定义 WebDriver 等待条件的最长时间,以及我们希望检查条件的频率,然后抛出“ElementNotVisibleException”异常。它以固定的时间间隔检查网页元素,直到找到对象或超时发生。

频率:设置一个重复周期,并指定时间范围,以定期检查/验证条件

让我们考虑一个场景,其中元素以不同的时间间隔加载。如果我们将显式等待设置为 20 秒,元素可能会在 10 秒、20 秒甚至更长时间内加载。它将等待到指定时间后才抛出异常。在这种情况下,流畅等待是理想的等待方式,因为它将以不同的频率尝试查找元素,直到找到它或最终计时器用完。

流畅等待语法

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("https://demo.guru99.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);				

在上面的示例中,我们声明了一个流畅等待,超时时间为 30 秒,频率设置为 5 秒,并忽略了“NoSuchElementException

考虑以下代码

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 秒。这意味着它将每 5 秒检查网页上的元素,最长检查时间为 30 秒。如果在此时间范围内找到元素,它将执行操作,否则将抛出“ElementNotVisibleException

另请查看:- Selenium IDE 初学者教程

隐式等待与显式等待的区别

以下是 Selenium 中隐式等待和显式等待的主要区别

隐式等待 显式等待
隐式等待时间应用于脚本中的所有元素 显式等待时间仅应用于我们指定的元素
在隐式等待中,我们无需指定要定位元素的“预期条件” 在显式等待中,我们需要指定要定位元素的“预期条件”
当元素在 Selenium 隐式等待中指定的时间范围内定位时,建议使用此方法 当元素加载时间较长,并且需要验证元素的属性(如 visibilityOfElementLocated、elementToBeClickable、elementToBeSelected)时,建议使用此方法。

结论

隐式、显式和流畅等待是 Selenium 中使用的不同等待方式。这些等待的使用完全基于以不同时间间隔加载的元素。在测试我们的应用程序或构建我们的框架时,始终不建议使用 Thread.Sleep()。

另请查看:- Selenium 初学者教程:7 天学习 WebDriver