Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selenium WebDriver: Fluent wait works as expected, but implicit wait does not

I am new to Selenium WebDriver and am trying to understand the correct way to 'wait' for elements to be present.

I am testing a page with a bunch of questions that have radio button answers. As you select answers, Javascript may enable/disable some of the questions on the page.

The problem seems to be that Selenium is 'clicking too fast' and not waiting for the Javascript to finish. I have tried solving this problem in two ways - explicit waits solved the problem. Specifically, this works, and solves my issue:

private static WebElement findElement(final WebDriver driver, final By locator, final int timeoutSeconds) {     FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver)             .withTimeout(timeoutSeconds, TimeUnit.SECONDS)             .pollingEvery(500, TimeUnit.MILLISECONDS)             .ignoring(NoSuchElementException.class);      return wait.until(new Function<WebDriver, WebElement>() {         public WebElement apply(WebDriver webDriver) {             return driver.findElement(locator);         }     }); } 

However, I would prefer to use an implicit wait instead of this. I have my web driver configured like this:

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

This does not solve the problem and I get a NoSuchElementException. Additionally, I do not notice a 10 second pause - it just errors out immediately. I have verified this line in the code is being hit with a debugger. What am I doing wrong? Why does implicitlyWait not wait for the element to appear, but FluentWait does?

Note: As I mentioned I already have a work around, I really just want to know why Implicit wait isn't solving my issue. Thanks.

like image 238
emulcahy Avatar asked Aug 20 '12 15:08

emulcahy


People also ask

What is the difference between fluent wait and implicit wait?

For example setting an implicit wait of 10 seconds and an explicit wait of 15 seconds, could cause a timeout to occur after 20 seconds. the Fluent wait is when we can set up a repeat time cycle to verify the condition is met or not.

Why implicit wait is not recommended?

Hey Aaron, the main disadvantage of implicit wait is that it slows down test performance. The implicit wait will tell to the web driver to wait for certain amount of time before it throws a "No Such Element Exception". The default setting is 0.

Is implicit wait deprecated in Selenium?

Method SummaryDeprecated. Use implicitlyWait(Duration) Specifies the amount of time the driver should wait when searching for an element if it is not immediately present. Specifies the amount of time the driver should wait when searching for an element if it is not immediately present. Deprecated.

What is the difference between WebDriver wait and fluent wait?

Class WebDriverWait is a disciplined child (Specialization) of Class FluentWait and grand child of interface Wait. In short, Class FluentWait implements Wait interface and WebDriverWait extends FluentWait. You can set polling interval in both instances. You can ignore any exceptions in both instances.

How to use fluentwait in selenium with WebDriver?

Fluent Wait syntax: Wait wait = new FluentWait(WebDriver reference) .withTimeout(timeout, SECONDS) .pollingEvery(timeout, SECONDS) .ignoring(Exception.class); Above code is deprecated in Selenium v3.11 and above. You need to use

What is explicit Wait in selenium?

The Explicit Wait in Selenium is used to tell the Web Driver to wait for certain conditions (Expected Conditions) or maximum time exceeded before throwing “ElementNotVisibleException” exception. It is an intelligent kind of wait, but it can be applied only for specified elements.

What is the correct syntax for using explicit Wait in WebDriver?

Explicit Wait syntax: WebDriverWait wait = new WebDriverWait(WebDriverRefrence,TimeOut);

How to use timeoutexception in Selenium WebDriver to execute script faster?

The above code instructs Selenium WebDriver to wait for 30 seconds before throwing a TimeoutException. If it finds the element before 30 seconds, then it will return immediately. After that, it will click on the “Compose” button. In this case, the program will not wait for the entire 30 seconds, thus saving time and executing the script faster.


2 Answers

Remember that there is a difference between several scenarios:

  • An element not being present at all in the DOM.
  • An element being present in the DOM but not visible.
  • An element being present in the DOM but not enabled. (i.e. clickable)

My guess is that if some of the page is being displayed with javascript, the elements are already present in the browser DOM, but are not visible. The implicit wait only waits for an element to appear in the DOM, so it returns immediately, but when you try to interact with the element you get a NoSuchElementException. You could test this hypothesis by writing a helper method that explicits waits for an element to be be visible or clickable.

Some examples (in Java):

public WebElement getWhenVisible(By locator, int timeout) {     WebElement element = null;     WebDriverWait wait = new WebDriverWait(driver, timeout);     element = wait.until(ExpectedConditions.visibilityOfElementLocated(locator));     return element; }  public void clickWhenReady(By locator, int timeout) {     WebDriverWait wait = new WebDriverWait(driver, timeout);     WebElement element = wait.until(ExpectedConditions.elementToBeClickable(locator));     element.click(); } 
like image 104
Hedley Avatar answered Sep 20 '22 18:09

Hedley


basic idea is in the following:

Explicit wait

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

Implicit wait

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

In other words, explicit is associated with some condition to be held, whereas implicit with some time to wait for something. see this link

To make work fluentWait properly try this:

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

Hope this helps)

like image 26
eugene.polschikov Avatar answered Sep 22 '22 18:09

eugene.polschikov