Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I ask the Selenium-WebDriver to wait for few seconds in Java?

I'm working on a Java Selenium-WebDriver. I added

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

and

WebElement textbox = driver.findElement(By.id("textbox")); 

because my Applications takes few seconds to load the User Interface. So I set 2 seconds implicitwait. but I got unable to locate element textbox

Then I add Thread.sleep(2000);

Now it works fine. Which one is a better way?

like image 521
Rajaa Avatar asked Oct 12 '12 12:10

Rajaa


2 Answers

Well, there are two types of wait: explicit and implicit wait. The idea of explicit wait is

WebDriverWait.until(condition-that-finds-the-element); 

The concept of implicit wait is

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

You can get difference in details here.

In such situations I'd prefer using explicit wait (fluentWait in particular):

public WebElement fluentWait(final By locator) {     Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)             .withTimeout(30, TimeUnit.SECONDS)             .pollingEvery(5, TimeUnit.SECONDS)             .ignoring(NoSuchElementException.class);      WebElement foo = wait.until(new Function<WebDriver, WebElement>() {         public WebElement apply(WebDriver driver) {             return driver.findElement(locator);         }     });      return  foo; }; 

fluentWait function returns your found web element. From the documentation on fluentWait: An implementation of the Wait interface that may have its timeout and polling interval configured on the fly. 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. Details you can get here

Usage of fluentWait in your case be the following:

WebElement textbox = fluentWait(By.id("textbox")); 

This approach IMHO better as you do not know exactly how much time to wait and in polling interval you can set arbitrary timevalue which element presence will be verified through . Regards.

like image 162
eugene.polschikov Avatar answered Sep 28 '22 02:09

eugene.polschikov


This thread is a bit older, but thought I'd post what I currently do (work in progress).

Though I'm still hitting situations where the system is under heavy load and when I click a submit button (e.g., login.jsp), all three conditions (see below) return true but the next page (e.g., home.jsp) hasn't started loading yet.

This is a generic wait method that takes a list of ExpectedConditions.

public boolean waitForPageLoad(int waitTimeInSec, ExpectedCondition<Boolean>... conditions) {     boolean isLoaded = false;     Wait<WebDriver> wait = new FluentWait<>(driver)             .withTimeout(waitTimeInSec, TimeUnit.SECONDS)             .ignoring(StaleElementReferenceException.class)             .pollingEvery(2, TimeUnit.SECONDS);     for (ExpectedCondition<Boolean> condition : conditions) {         isLoaded = wait.until(condition);         if (isLoaded == false) {             //Stop checking on first condition returning false.             break;         }     }     return isLoaded; } 

I have defined various reusable ExpectedConditions (three are below). In this example, the three expected conditions include document.readyState = 'complete', no "wait_dialog" present, and no 'spinners' (elements indicating async data is being requested).

Only the first one can be generically applied to all web pages.

/**  * Returns 'true' if the value of the 'window.document.readyState' via  * JavaScript is 'complete'  */ public static final ExpectedCondition<Boolean> EXPECT_DOC_READY_STATE = new ExpectedCondition<Boolean>() {     @Override     public Boolean apply(WebDriver driver) {         String script = "if (typeof window != 'undefined' && window.document) { return window.document.readyState; } else { return 'notready'; }";         Boolean result;         try {             result = ((JavascriptExecutor) driver).executeScript(script).equals("complete");         } catch (Exception ex) {             result = Boolean.FALSE;         }         return result;     } }; /**  * Returns 'true' if there is no 'wait_dialog' element present on the page.  */ public static final ExpectedCondition<Boolean> EXPECT_NOT_WAITING = new ExpectedCondition<Boolean>() {     @Override     public Boolean apply(WebDriver driver) {         Boolean loaded = true;         try {             WebElement wait = driver.findElement(By.id("F"));             if (wait.isDisplayed()) {                 loaded = false;             }         } catch (StaleElementReferenceException serex) {             loaded = false;         } catch (NoSuchElementException nseex) {             loaded = true;         } catch (Exception ex) {             loaded = false;             System.out.println("EXPECTED_NOT_WAITING: UNEXPECTED EXCEPTION: " + ex.getMessage());         }         return loaded;     } }; /**  * Returns true if there are no elements with the 'spinner' class name.  */ public static final ExpectedCondition<Boolean> EXPECT_NO_SPINNERS = new ExpectedCondition<Boolean>() {     @Override     public Boolean apply(WebDriver driver) {         Boolean loaded = true;         try {         List<WebElement> spinners = driver.findElements(By.className("spinner"));         for (WebElement spinner : spinners) {             if (spinner.isDisplayed()) {                 loaded = false;                 break;             }         }         }catch (Exception ex) {             loaded = false;         }         return loaded;     } }; 

Depending on the page, I may use one or all of them:

waitForPageLoad(timeoutInSec,             EXPECT_DOC_READY_STATE,             EXPECT_NOT_WAITING,             EXPECT_NO_SPINNERS     ); 

There are also predefined ExpectedConditions in the following class: org.openqa.selenium.support.ui.ExpectedConditions

like image 31
Jeff Vincent Avatar answered Sep 28 '22 04:09

Jeff Vincent