Steve Staple
Steve Staple

Reputation: 3289

TestNG Java Selenium. What are the alternatives to Thread.sleep()

According to a number of articles I have seen, the use of Thread.sleep() seems to be frowned upon. I have used this frequently in my test classes, where it was necessary to wait for something to load. I have tried using this method to tell me when load is complete, but that did not help. It is not a reliable method.:

try {
        return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
                || ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
    } catch (Exception e) {
        System.err.println(thisClass + " Exception caught: " + e.getMessage());
    }

What alternatives methods can I use?

This solution worked:

  1. Calling function:

    String className = "gwt-Button form-control btn back-button ripple-container";
    String textToFind = "back-button-icon";
    String htmlElement = "button";
    boolean isReady = Common.FluentWait(driver, 60, className, textToFind, htmlElement);
    
  2. That function:

    public static boolean FluentWait(WebDriver driver, int timeOut, String className, String textToFind,
        String htmlElement) {
    // Waiting timeOut seconds for an element to be present on the page, checking
    // for its presence once every 5 seconds.
    Common.myPrint(thisClass + " FluentWait. ");
    Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(timeOut, TimeUnit.SECONDS)
            .pollingEvery(5, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
    
    WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
        public WebElement apply(WebDriver driver) {
            Common.myPrint(thisClass + " run returnWebElement. ");
            return returnWebElement(className, textToFind, htmlElement, driver);
        }
    });
    
    if (foo != null) {
        return true;
    }
    return false;
    

    }

and the function I called inside that:

public static WebElement returnWebElement(String className, String textToFind, String htmlElement,
        WebDriver driver) {

    List<WebElement> elements = Common.findElementsUsingHtmlXpathClass(driver, htmlElement, className);

    Common.myPrint(thisClass + " elements count: " + elements.size());
    String text = "";
    for (WebElement element : elements) {
        // select an element
        if (element.isDisplayed()) {
            text = element.getAttribute("innerHTML");
            if (text != "") {
                text = text.trim();
                if (text.contains(textToFind)) {
                    Common.myPrint(thisClass + " innerHTML: " + text);
                    Common.myPrint(thisClass + " returning element found. ");
                    return element;
                }
            }
        }
    }
    Common.myPrint(thisClass + " element not found. ");
    return null;
}

Upvotes: 3

Views: 1453

Answers (3)

JASmith
JASmith

Reputation: 31

I have found another way although it is very similar to Thread.sleep(). I was looking for another wait as the implicit wait and explicit wait with Selenium is not waiting long enough for me.

The alternative I used:

TimeUnit.SECONDS.sleep(int timeUnit)

This delivered the same functionality as Thread.sleep(). I hope this helps.

Upvotes: 3

JeffC
JeffC

Reputation: 25686

Your code will just attempt to wait for the page to load, not wait for specific elements, etc. to load. This will work fine for static HTML pages but once you start adding dynamic sections to the page (using AJAX, etc.) , it will not accomplish what you want.

You can use WebDriverWait. See the docs for more info.

Simple example,

// create an instance that can be reused
WebDriverWait wait = new WebDriverWait(driver, 10);
// wait for an element to be clickable and store the return
WebElement button = wait.until(ExpectedConditions.elementToBeClickable(By.id("someId"));
// click the returned button
button.click();

There are a bunch of standard conditions provided by ExpectedConditions. See the docs for more info.

Upvotes: 1

Roushan
Roushan

Reputation: 4440

You can use FluentWait

Each FluentWait instance defines the maximum amount of time to wait for a condition, as well as the frequency with which to check the condition. Furthermore, the user may configure the wait to ignore specific types of exceptions whilst waiting, such as NoSuchElementExceptions when searching for an element on the page.

/* 
code snippet will Wait 30 seconds for 
an element to be present on the page and check for its 
presence once every 5 seconds.
*/
Wait wait = new FluentWait(driver)
    .withTimeout(30, SECONDS)
    .pollingEvery(5, SECONDS)
    .ignoring(NoSuchElementException.class);

WebElement foo = wait.until(new Function() {
    public WebElement apply(WebDriver driver) {
        return driver.findElement(By.id("foo"));
    }
});

another wait also available

Upvotes: 4

Related Questions