Waiting For Elements In Selenium

dimitrilc 2 Tallied Votes 67 Views Share

Introduction

When working with Selenium, you might have run into a situation where you have to wait for long-running tasks to complete before you can interact with elements. Fortunately, Selenium has support for such situations via its many waits API.

In this tutorial, we will learn how to wait for the web page with Selenium.

Goals

At the end of the tutorial, you would have learned:

  1. How to wait for long-running tasks with Selenium.

Tools Required

  1. A Java IDE such as IntelliJ IDEA version 2022.2 (Community Edition).

Prerequisite Knowledge

  1. Basic Java.
  2. Basic Selenium.
  3. Basic Spring.

Project Setup

To follow along with the tutorial, perform the steps below:

  1. Clone this repository, switching to the waits branch.

Explicit Wait

First, let us get started with learning about Explicit Waits. The word explicit here refers to the element that you are waiting on, and not about the waiting time. Whether you are using explicit wait or implicit wait, you must specify a timer.

In our project, the end point “/waits” would take up to 5 seconds to load the words “Hello World!”. What do you think will happen to the test below when run?

@Test
void explicitWait(){
 driver.get("http://localhost:" + port + "/waits");

 new WebDriverWait(driver, Duration.ofSeconds(4))
       .until(_d -> driver.findElement(By.cssSelector("p")));
}

Well, because we have only waited for four seconds, it obviously would fail with a TimeOutException because the timer has elapsed before the <p> is added to the page.

org.openqa.selenium.TimeoutException: Expected condition failed: waiting for com.daniweb.selenium.SeleniumApplicationTests$$Lambda$1358/0x00000008007e7c18@fd0e118 (tried for 4 second(s) with 500 milliseconds interval)

For the test to work properly, we can simply wait for 6 seconds instead, so that the <p> element would have loaded already.

@Test
void explicitWait(){
 driver.get("http://localhost:" + port + "/waits");

 new WebDriverWait(driver, Duration.ofSeconds(6))
       .until(_d -> driver.findElement(By.cssSelector("p")));
}

The explicit condition inside until() is what makes this wait an explicit wait.

Implicit Wait

Similarly to an explicit wait, an implicit wait would also have to specify a timeout amount. There are two main differences between an explicit and an implicit wait:

  1. An implicit wait is set using a different API, driver().manage().implicitWait(), instead of the WebDriverWait class.
  2. Once you set an implicit wait, it is valid for the life of the session.
  3. You do not have to specify an element for implicit waits. The wait simply applies to all elements that you try to find.

Here is a sample test that uses implicit wait.

@Test
void implicitWait(){
  driver.get("http://localhost:" + port + "/waits");
  driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(6));

  var p = driver.findElement(By.cssSelector("p"));
}

Implicit wait can be particularly useful when you do not want to repeatedly type out explicit waits that have the same duration. For example, the explicit wait test below waits for three different elements with the same duration of 5 seconds.

@Test
void repeatedExplicitWaits(){
  driver.get("http://localhost:" + port + "/waits");

  new WebDriverWait(driver, Duration.ofSeconds(5))
        .until(_d -> driver.findElement(By.cssSelector("p")));

  new WebDriverWait(driver, Duration.ofSeconds(5))
        .until(_d -> driver.findElement(By.cssSelector("a")));

  new WebDriverWait(driver, Duration.ofSeconds(5))
        .until(_d -> driver.findElement(By.cssSelector("h1")));
}

We could save a couple of lines and use implicit waits, like below.

@Test
void shortImplicitWait(){
  driver.get("http://localhost:" + port + "/waits");
  driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));

  var p = driver.findElement(By.cssSelector("p"));
  var a = driver.findElement(By.cssSelector("a"));
  var h1 = driver.findElement(By.cssSelector("h1"));
}

Summary

We have learned how to use implicit and explicit waits in Selenium. The full project code can be found at https://github.com/dmitrilc/Daniweb_Selenium/tree/waits.