Selenium 等待 – 隐式和显式以及语法
在 Selenium 中,“等待”在执行测试时扮演着重要的角色。在本教程中,您将学习 Selenium 中隐式等待和显式等待的各种方面及其区别。
为什么我们需要在 Selenium 中使用等待?
大多数 Web 应用程序都是使用 Ajax 和 Javascript 开发的。当浏览器加载页面时,我们想要交互的元素可能会在不同的时间间隔加载。
这不仅使识别元素变得困难,而且如果找不到元素,它还会抛出“ElementNotVisibleException”异常。使用 Selenium 等待,我们可以解决这个问题。
让我们考虑一个场景,我们必须在测试中同时使用隐式等待和显式等待。假设隐式等待时间设置为 20 秒,显式等待时间设置为 10 秒。
假设我们正在尝试查找具有某些“ExpectedConditions”(显式等待)的元素,如果元素未在显式等待定义的时间范围(10 秒)内找到,它将使用隐式等待定义的时间范围(20 秒)才能抛出“ElementNotVisibleException”。
Selenium WebDriver 等待
- 隐式等待
- 显式等待
在本教程中,您将学习 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 显式等待中使用的预期条件
- alertIsPresent()
- elementSelectionStateToBe()
- elementToBeClickable()
- elementToBeSelected()
- frameToBeAvaliableAndSwitchToIt()
- invisibilityOfTheElementLocated()
- invisibilityOfElementWithText()
- presenceOfAllElementsLocatedBy()
- presenceOfElementLocated()
- textToBePresentInElement()
- textToBePresentInElementLocated()
- textToBePresentInElementValue()
- titleIs()
- titleContains()
- visibilityOf()
- visibilityOfAllElements()
- visibilityOfAllElementsLocatedBy()
- 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