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.
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.
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.
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.
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.
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
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.
Explicit Wait syntax: WebDriverWait wait = new WebDriverWait(WebDriverRefrence,TimeOut);
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.
Remember that there is a difference between several scenarios:
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(); }
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With