Sig
Sig

Reputation: 133

How tell JAVA Selenium WebDriver to wait for specific time period without Thread.sleep()

I'm trying to write a simple UI test with Selenium, TestNG and Hamcrest. The problem is that webshop (Opencart) which I'm using as testing playground uses the same classes for displaying featured products in front page and search results. My test method:

    @DataProvider(name = "searchDataIterator")
public Iterator<Object> searchDataProviderWithIterator(){
   return new ArrayList<Object>(Arrays.asList("macbook", "iphone", "tv", "nokia", "hat")).iterator();
}

@Test(groups = "generic", dataProvider = "searchDataIterator", priority = 4)
public void runSearchWithDataProvider(String searchData) throws InterruptedException {
    driver.findElement(By.cssSelector("#search input")).clear();
    driver.findElement(By.cssSelector("#search input")).sendKeys(searchData, Keys.ENTER);
    Thread.sleep(500);
    assertThat(driver.findElements(By.className("product-thumb")).size(), is(greaterThan(0)));
}

Problem is that if I dont't use Thread.sleep(500); the line assertThat(driver.findElements(By.className("product-thumb")).size(), is(greaterThan(0))); catches either Featured product count from front page or results from previous search. I was told that using Therad.sleep() is very bad practice, but how to achieve same thing without it?

Upvotes: 2

Views: 2051

Answers (4)

freitas
freitas

Reputation: 313

You can import

import java.awt.Robot;

and use its delay method passing how many milliseconds (ms) to wait. Example:

Robot robot = new Robot();
robot.delay(1000); // 1 SECOND

Robot has a MAX_DELAY constant value that allows to wait at most for 60 seconds

private static final int MAX_DELAY = 60000;

Upvotes: 0

timbre timbre
timbre timbre

Reputation: 13995

My suggestion would be to use 2-stage approach:

  1. Wait for something that indicates transition to results have happened. Not results themselves, but some element that indicates that page transitioned to search result.

  2. After that, you can wait for/get results themselves, like @Alan-Barboza suggested

Using demo.opencart.com, step 1 would look like this:

WebDriverWait wait = new WebDriverWait(driver, 10);

// Step 1: wait for page to navigate to search results
// identified by <h1> with text 'Search - [search term]'
wait.until(ExpectedConditions.presenceOfElementLocated(
  By.xpath("//h1[contains(text(), 'Search - " + searchData + "')]")));

A bonus is that if test fails at this step, you'd know the actual reason: page never navigated to search results, as opposed to search didn't find expected products.

Upvotes: 2

Bill Hileman
Bill Hileman

Reputation: 2836

Try the following code which, as its name implies, waits for the page to load:

public static void waitForPageToLoad() {
    WebDriverWait wait = new WebDriverWait(driver, 10);
    wait.until(new ExpectedCondition<Boolean>() {

        public Boolean apply(WebDriver wdriver) {
            return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
        }
    });
}

Upvotes: 0

Alan Barboza
Alan Barboza

Reputation: 125

Try use code bellow, it will solve the issue:

List<WebElement> productThumbs = new WebDriverWait(driver, 500)
    .until(new Function<WebDriver, WebElement>() {
        public WebElement apply(WebDriver driver) {
            return driver.findElements(By.className("product-thumb"));
        }
    });
assertThat(productThumbs.size(), is(greaterThan(0)));

Upvotes: 0

Related Questions