Skip to main content

Jun 30, 2020 - 3 minute read - Selenium WebDriver FAQs Test Automation

How to Wait with WebDriver

How to synchronise on application state? How to Wait with WebDriver? Thread.sleep is not the answer, so what is?

Avoid Thread.sleep

The main thing we want to avoid is a Thread.sleep

If you do use Thread.sleep make it obvious what you are doing.

But do not rely on this for strategic automating.

    private void pauseToAllowVisibility() {
        try{
            Thread.sleep(1000);
        }catch(Exception e){
            // ignore
        }
    }

For more information about Thread.sleep, check this blog post.

Waiting

Waiting in WebDriver uses a WebDriverWait

driver.get("https://testpages.herokuapp.com/styled/calculator");
new WebDriverWait(driver,10).
      until(
        // some ExpectedCondition to wait for
       );

And the WebDriverWait can be assigned to a variable for re-use.

e.g.

WebDriverWait wait = new WebDriverWait(driver,10);

ExpectedConditions

I remember back in 2012 reading through the WebDriver code and finding a support class for ExpectedConditions class which exposes a bunch of static methods to save me having to write code.

ExpectedConditions contains a lot of common waiting conditions.

The ExpectedConditions class has a method waiting for a page title to contain some text.

driver.get("https://testpages.herokuapp.com/styled/calculator");
new WebDriverWait(driver,10).
                 until(ExpectedConditions.titleContains("Selenium"));

Creating Your Own ExpectedCondition

I can create and use my own ExpectedCondition classes:

driver.get("https://testpages.herokuapp.com/styled/calculator");
new WebDriverWait(driver,10).
         until(new TitleContainsCondition("Selenium"));

This opens the driver to the page and waits until the Title contains the text “Selenium”.

And I would write code to support this i.e. my TitleContainsCondition class:

public class TitleContainsCondition implements ExpectedCondition {
    private String subMenuText;

    public TitleContainsCondition(final String subMenuText) {
        this.subMenuText=subMenuText;
    }

    @Override
    public Boolean apply(@Nullable WebDriver driver) {
        return driver.getTitle().contains(this.subMenuText);
    }
}

Create Your Own ExpectedConditions

If I want a custom ExpectedConditions then I can create my own ‘factory’ class to return ExpectedCondition

driver.get("https://testpages.herokuapp.com/styled/calculator");
new WebDriverWait(driver,10).
                 until(WaitFor.titleContainsCondition("Selenium"));

I do occasionally write a WaitFor Class to add application or non-standard conditions, since we test applications which are domain specific.

And the WaitFor would look like:

public class WaitFor {

    public static ExpectedCondition<Boolean> titleContainsCondition(String titleMustContain) {
        return new TitleContainsCondition(titleMustContain);
    }
}

Inline

If I really wanted to I could use a WebDriverWait without a separate class.

    @Test
    public void useInLineExpectedCondition(){
        driver.get("https://testpages.herokuapp.com/styled/calculator");
        new WebDriverWait(driver,10)
            .until(
                    new ExpectedCondition<Boolean>(){
                        @Override
                        public Boolean apply(WebDriver driver) {
                            return driver.getTitle().startsWith("Selenium");
                        }
                    }
                );
    }

But I haven’t written any code like this for some time. If I use a wait then I would refactor it into a class of its own, or wrap it as a factory method e.g. on WaitFor

Lambda

With Java 8 it is now possible to use waits in closure/lambda expressions.

    @Test
    public void useViaLambdaExpressions(){
        driver.get("https://testpages.herokuapp.com/styled/calculator");

        WebDriverWait wait = new WebDriverWait(driver,10);
        ExpectedCondition<Boolean> titleStartsWithSelenium = mydriver ->
                            { return mydriver.getTitle().startsWith("Selenium");};

        wait.until(titleStartsWithSelenium);
    }

I rarely use this, but sometimes for adhoc experimentation or workarounds I do.

Historical Note

WebDriver initial implementation of waiting was much more basic.

e.g. here is some code from 2011(ish)

 new Wait("JS Page title did not change"){

     @Override   
     public boolean until() {   
         try{   
             return driver.getTitle().startsWith("Selenium"));   
         }catch(Exception e){   
             // ignore not found exception   
         }   
         return false;   
     }              
 };

Note: this post was originally written in 2011, hence the ‘historical note’ example, and updated on 20200603.

Full Source

The full source for this is in my Webdriver Java FAQs project:

Specifically:

If you want to learn how to use Selenium WebDriver with Java then check out our online courses. We have course dedicated to Advanced Synchronisation, and one dedicated to the Support Classes.


You will need a Github account to comment. Or you can contact me with your comment.

I reserve the right to delete spam comments e.g. if your comment adds no value and its purpose is simply to create a backlink to another site offering training, or courses, etc.