Add some ‘Weight’ to your Selenium Tests with ‘Waits’! – Part 1: Implicit Waits

In this series of blog posts we are going to learn about a fundamental component of Selenium tests – waits. Why would we need to use waits in our tests? Well whenever you are using a webpage you will often find that certain elements are not available on the page right away, either because they are still being loaded or for some other reason. Without any waits in your scripts, if Selenium can’t find the requested element straight away then the script will throw an error and the test will fail. It might have just been the case that the element needed a second or two to load onto the page, but Selenium just couldn’t wait that long and threw you a big nasty error message.

There are three main types of wait used in Selenium and we will look at them all individually. We will begin today with probably the simplest one to use – implicit waits. When you set an implicit wait, you are basically setting a timeout for every single action in your test. They are very simple to implement, since they only need to be set once, and are a good way to quickly and easily add some waits to your scripts.

When an implicit wait has been set in your test and Selenium performs an action such as finding an element, if that element cannot be found straight away then Selenium will wait for the amount of time set in the implicit wait and then try again.

Ok, let’s go through an example and see if we can make things a bit clearer. Go ahead and right-click on your ‘java > test’ folder as usual and create a new class called ‘MyFirstWaitTests‘. Add the following setup code to the class:

public class MyFirstWaitTests {

    public static FirefoxDriver driver;

    @BeforeClass
    public static void setupDriver()
    {
        driver = new FirefoxDriver();

        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
    }

    @Before
    public void goToAccountPage()
    {
        driver.get("http://store.demoqa.com/products-page/your-account/");
    }
        
    @AfterClass
    public static void quitDriver()
    {
        driver.quit();
    }
}

The only new bit of code here is:

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

Here we are telling Selenium to implicitly wait for 10 seconds at every step of the test if the requested action cannot be completed straight away and keep trying.

For our first example we are going to use the accounts page at Tools QA again – here . We are going to write two tests that each look up an element on the page. One of the elements will exist, one will not. Go ahead and add the following two tests between the @BeforeClass and the @AfterClass:

    @Test
    public void findAnElement_ShouldPass()
    {
        WebElement loginField = driver.findElement(By.id("log"));
    }

    @Test
    public void findAnElement_ShouldFail()
    {
        WebElement someField = driver.findElement(By.id("doesNotExist"));
    }

Go ahead and run the two tests. The first test should pass as expected in a very quick time. The second test will fail, again as expected, but will take longer to run. As described above this is because Selenium will look for the element, see that it is not available, continue trying for 10 seconds, see that it is STILL not available, and throw an error in the test:
ImplicitWait1Implicit waits are a good way to get started in Selenium, and I find them particularly useful in the early stages of writing my tests when my scripts are still in a development phase. However, they are not perfect and they do pose a few issues.
Firstly, they can slow the tests down much more than is necessary. Suppose you have an implicit wait set for 10 seconds as in this example, but the element on your page is broken and won’t load. The test will wait for the full 10 seconds before throwing the error, wasting a whole 9 seconds. This does not sound like a lot, but believe me, when you get to the stage that you have hundreds of automated tests running on a regular basis this lost time is significant and frustrating.

Another issue is that implicit waits are not particularly flexible. When we set the implicit wait at the start of the test we are setting that wait for every action throughout the test. There are ways around this, as I will show you in a later post, but they are another drawback.

I am going to show you another example that demonstrates another problem with implicit waits. For this example, we are going to use a page from ‘The Internet’ website at – http://the-internet.herokuapp.com/dynamic_loading/2 . On this page when the user clicks on the start button, there is a loading period of a few seconds before the text ‘Hello World‘ appears on the screen. The element for ‘Hello World’ is only rendered in the code after the loading bar disappears, so without enough of a wait the test will fail since it won’t be able to find the element right away.

Let’s create a new test class for this example. Right-click on ‘test > java’ in Intellij and create a new class called ‘FailingImplicitWaitTest‘. Add the following code to the class:

public class FailingImplicitWaitTest {

    public static FirefoxDriver driver;

    @BeforeClass
    public static void createDriver()
    {
        driver = new FirefoxDriver();
    }

    @Test
    public void failingImplicitWaitTest()
    {
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);

        driver.get("http://the-internet.herokuapp.com/dynamic_loading/2");

        WebElement startButton = driver.findElement(By.cssSelector("#start>button"));

        startButton.click();

        WebElement helloWorldText = driver.findElement(By.id("finish"));
    }

    @AfterClass
    public static void quitDriver()
    {
        driver.quit();
    }
}

Go ahead and run the test, it will fail. Why does it fail? Well we only set the implicit wait to be 3 seconds, but the element takes 5 seconds to appear after clicking the start button. A simple solution would be to just increase the implicit wait to say 10 seconds, but as we talked about above this will have a massive knock-on effect in a large test suite. Additionally, where do you draw the line? Increasing to 5 or 10 seconds from 3 seconds is perhaps not that big of a deal, but what about if you have an element that takes 60 seconds (or longer) to load?

You are probably thinking that there must be a better way, and you will be pleased to know that there is! In the next post, we are going to look at explicit waits. The official Selenium documentation recommends to use explicit waits over implicit waits, and we are going to find out why.

Click here to go to Part 2: Explicit Waits