🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# Selenium WebDriver 中的隐式,显式&流利等待 > 原文: [https://www.guru99.com/implicit-explicit-waits-selenium.html](https://www.guru99.com/implicit-explicit-waits-selenium.html) 在硒中,“等待”在执行测试中起着重要作用。 在本教程中,您将学习 Selenium 中“隐式”和“显式”等待的各个方面。 在本教程中,您将学习: * [为什么我们需要硒中的等待?](#1) * [隐式等待](#2) * [显式等待](#3) * [流利的等待](#4) ## 为什么我们需要硒? 大多数 Web 应用程序都是使用 Ajax 和 Javascript 开发的。 当浏览器加载页面时,我们要与之交互的元素可能会在不同的时间间隔加载。 这不仅使识别元素变得困难,而且如果没有找到该元素,也会引发“ **ElementNotVisibleException** ”异常。 使用等待,我们可以解决此问题。 让我们考虑一下在测试中必须同时使用隐式和显式等待的情况。 假定隐式等待时间设置为 20 秒,显式等待时间设置为 10 秒。 假设我们正在尝试找到一个具有**“ ExpectedConditions** ”(显式等待)的元素,如果该元素不在显式等待(10 秒)定义的时间范围内,它将使用该时间 由隐式等待(20 秒)定义的帧,然后抛出“ **ElementNotVisibleException** ”。 **Selenium Web 驱动程序等待** 1. 隐式等待 2. 显式等待 ## 隐式等待 Selenium Web Driver 从 Watir 借用了隐式等待的想法。 隐式等待将告诉 Web 驱动程序等待一定的时间,然后再引发“无此类元素异常”。 默认设置为 0。一旦设置了时间,Web 驱动程序将等待该时间,然后引发异常。 在下面的示例中,我们声明了一个隐式等待,其时间范围为 10 秒。 这意味着,如果该元素不在该时间段内位于网页上,它将引发异常。 声明隐式等待: **语法**: ``` 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://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 个参数,第一个参数将接受时间作为整数值,第二个参数将接受以秒,分钟,英里,微秒,纳秒,天,小时等为单位的时间度量。 ## 显式等待 显式等待用于告诉 Web 驱动程序等待某些条件(**预期条件**)或在引发“ **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("http://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(); } } ``` **Explanation of Code** **Consider Following Code:** ``` 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(); ``` 在上面的示例中,等待在“ **WebDriverWait** ”类或“ **ExpectedConditions** ”类中定义的时间发生,以先到者为准。 上面的 [Java](/java-tutorial.html) 代码指出,我们正在等待元素的时间为 20 秒(如网页上的 **WebDriverWait** 类中所定义的),直到[ **ExpectedConditions** 满足,条件为“ **visibleofElementLocated** ”。 以下是可以在显式等待中使用的预期条件 1. alertIsPresent() 2. elementSelectionStateToBe() 3. elementToBeClickable() 4. elementToBeSelected() 5. frameToBeAvaliableAndSwitchToIt() 6. invisibilityOfTheElementLocated() 7. invisibilityOfElementWithText() 8. presentOfAllElementsLocatedBy() 9. presentOfElementLocated() 10. textToBePresentInElement() 11. textToBePresentInElementLocated() 12. textToBePresentInElementValue() 13. titleIs() 14. titleContains() 15. visibleOf() 16. visibleOfAllElements() 17. visibleOfAllElementsLocatedBy() 18. visibleOfElementLocated() ## 流利的等待 流利的等待用于告诉 Web 驱动程序等待条件,以及在抛出“ ElementNotVisibleException”异常之前我们要用来检查条件的**频率**。 **频率:**设置一个具有时间范围的重复周期,以固定时间间隔验证/检查条件 让我们考虑一个场景,其中元素以不同的时间间隔加载。 如果我们声明显式等待 20 秒,则该元素可能会在 10 秒,20 秒甚至更长的时间内加载。 它会等到指定的时间,然后引发异常。 在这种情况下,流畅的等待是理想的等待方式,因为它将尝试以不同的频率查找元素,直到找到它或最终计时器用完为止。 **语法:** ``` Wait wait = new FluentWait(WebDriver reference) .withTimeout(timeout, SECONDS) .pollingEvery(timeout, SECONDS) .ignoring(Exception.class); ``` 在 Selenium v​​3.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://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() ; } } ``` **代码**的说明 **Consider Following Code:** ``` Wait<WebDriver> wait = new FluentWait<WebDriver>(driver) .withTimeout(30, TimeUnit.SECONDS) .pollingEvery(5, TimeUnit.SECONDS) .ignoring(NoSuchElementException.class); ``` 在上面的示例中,我们通过忽略“ **NoSuchElementException** ”声明了等待时间为 30 秒且频率设置为 5 秒的流畅等待 **Consider Following Code:** ``` 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 元素不过是网页上的硒链接)。 频率设置为 5 秒,最长时间设置为 30 秒。 因此,这意味着它将每 5 秒检查一次网页上的元素,最长时间为 30 秒。 如果元素位于此时间范围内,它将执行操作,否则将抛出“ **ElementNotVisibleException** ” ## 隐式等待与显式等待之间的差异 | <center>**隐式等待**</center> | <center>**显式等待**</center> | | * 隐式等待时间应用于脚本 中的所有元素 | * 显式等待时间仅适用于我们想要的那些元素 | | * 在隐式等待中,我们需要 **而不是** 在要定位的元素上指定“ ExpectedConditions” | * 在“显式等待”中,我们需要在要定位的元素上指定“ ExpectedConditions” | | * 当元素位于隐式等待 中指定的时间范围内时,建议使用 | * 建议在元素需要较长时间加载时使用,也建议用于验证元素的属性,例如(visibilityOfElementLocated,elementToBeClickable,elementToBeSelected) | **结论:** **隐式,显式**和**流利等待**是硒中使用的不同等待。 这些等待的使用完全基于在不同时间间隔加载的元素。 在[测试我们的应用程序或构建我们的框架时,始终不建议**使用** Thread.Sleep()。](/software-testing.html) ***本文由 Chaitanya Pujari 提供***