Skip to main content
blog title image

5 minute read - Selenium WebDriver FAQs Test Automation

How to Wait with WebDriver

Jun 30, 2020

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.

Wait Before or Wait After

In one of my early WebDriver training courses I had an exercise which involved waiting for an element to have clickability. It existed in the DOM, visible, and all other rendered event style isCondition()s. But when clicked on, it could not respond to events.

The initial approach involved trying to fix the problem at the point my code encountered it, i.e. when trying to click on it in the Page Object.

private void clickSubMenuItem(String subMenuText) {

    // insert lots of banging of head with failed automation code here
    // because the element below is visible but isn’t responding to clicks yet
    // can’t figure out how to detect if the element is responding to clicks
    // before I click on it because click doesn’t throw an exception
    // because it is there to click on

    String xpathExpression = //div[@class=\“GALD-WOBF\” and .=\“” + subMenuText + “\“]”;
    driver.findElement(By.xpath(xpathExpression)).click();
   
    wait.until(weCanSee.GWTTitleMatches(subMenuText));
}

The most robust solution for the automation issue by waiting, at the point my code puts the system into the state of unclickability, and waiting until it re-enters a state of clickability.

public void openClose() {
    WebDriverWait wait = new WebDriverWait(driver,20);
    ExpectedConditionFactory weCanSee = new ExpectedConditionFactory();

    By imageLocator = By.xpath(//div[.=\“”+ this.menuHeading + “\“]/../div/img”);
    driver.findElement(imageLocator).click();

    // This is the wait I needed in the code above, but it only made sense here
    // do not consider it open or closed until the menu stops growing,

    By parentDiv = By.xpath(//div[.=\“”+ this.menuHeading + “\“]/../../..”);
    wait.until(weCanSee.elementStopsGrowing(parentDiv, driver));
}

Both waiting styles offer valid automation choices.

I found it interesting that I defaulted to the first style and that caused intermittency issues. I don’t think I’ve used the second style as much.

You can imagine more trade-offs associated with each style:

1st Style – Before Follow On Actions

  • Tests might go faster because, follow on actions may not require earlier waits as guard conditions
  • Page objects become more complicated because we have to remember to check for all guard conditions before taking action
  • Guard checking happens in multiple places
  • Risk of test intermittency because of emergent behaviour which we might find hard to debug

2nd Style – Immediately After triggering condition

  • Exit condition checks in single place
  • Less chance of exposing emergent behaviour as application keeps synchronised to a ‘good’ state
  • Leads to doSomething and doSomethingAndWait style methods

For some reason my approach to automation defaulted to the first style.

This post should act as a reminder to consider both styles.

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.