Fluent Wait more info: Example
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. // Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 5 seconds.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("foo"));
}
});
Implicit wait Vs. Explicit wait
Implicit wait
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
Implicit waits are basically your way of telling WebDriver the latency that you want to see if specified web element is not present that WebDriver looking for. So in this case, you are telling WebDriver that it should wait 10 seconds in cases of specified element not available on the UI (DOM).
- Implicit wait time is applied to all elements in your script
Explicit wait (By Using FluentWait)
public static WebElement explicitWait(WebDriver driver,By by)
{
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(20, TimeUnit.SECONDS)
.pollingEvery(2, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement element= wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("foo"));
}
});
return element;
}
Explicit waits are intelligent waits that are confined to a particular web element. Using explicit waits you are basically telling WebDriver at the max it is to wait for X units of time before it gives up.
- Explicit wait time is applied only for particular specified element.
- In Explicit you can configure, how frequently (instead of 2 seconds) you want to check condition
Explicit wait
public static WebElement explicitWait(WebDriver driver,By by)
{
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.presenceOfElementLocated(by));
}
In above method it will wait until either ExpectedConditions become true or Timeout (30 sec).
Selenium Explicit Wait
Explicit wait is a programmatic approach to problem of waiting for
elements. Contrary to Implicit Wait that I have described in previous
article Explicit Wait requires more coding but also gives much more
flexibility. Any action that can be performed using WebDriver
can be wrapped using explicit wait and performed over defined period of
time checking custom condition. As fast as the condition is satisfied
test will continue and if condition was not satisfied for period longer
then defined threshold then TimeoutException
or any of the not ignored exceptions will be thrown. I will try to
address problems that I have described in article about Implicit Wait
and show how they can be solved using explicit approach.
1. Performance
What we would like is to have default timeout that will be used in most
cases but also possibility to change it if necessary. Fortunately this
is what FluentWait
class offers. Moreover we can define how frequently we should check the
condition. Knowing that we can solve problem of verifying that given
element is not present on the page implementing our own condition with
custom timeout or just use already provided conditions that are defined
in utility class called ExcepctedConditions.
2. Exceptions
Second interesting feature that we get out of the box by using FluentWait
is ability to ignore specific exceptions and provide custom message
that will be included in exception. No longer we have to start analyzing
our tests result from very detailed information about internals of WebDriver
or XPath. This is especially convenient when you are dealing with large
number of tests. Basically what we are doing is putting another layer
of user friendly information that is easier to analyze.
3. Reliability
This is where explicit approach really shines and probably most
important reason to use it, especially when testing pages with lot of
JavaScript. For example if we want to click on element that is present
in DOM but temporarily invisible we can create a condition that will
check both presence and visibility. If the element is moving we can try
to ignore WebDriverException knowing that we would end up with 'element is not clickable' (this is a bit more risky because WebDriverException can be thrown for other reasons). Finally if we are dealing with StaleElementReferenceException
we can try to ignore it and perform whole sequence of actions inside
condition body. This means we will periodically try to find element and
perform action on it instead of returning if from method and using it
later (when it is more likely to end up with stale reference).
4. Conditions
Explicit wait approach is not limited to only findElement and findElements methods of WebDriver.
We can use it to chain actions that would normally require few steps
and verifications along the way. For example we can define a custom
condition that will find input field, type some text and click ok
button. Moreover we can easily implement how to conditionally find
element. For example wait for progress bar to disappear and then look
for element. We can even ask a web developer to set some variable to
true if page was loaded or long running task had completed. Then we
would use JavascriptExecutor or WebDriver to find that variable and be sure that page is fully rendered and ready to use.
As you can see explicit approach requires more coding but also solves
many annoying problems you may run into using implicit wait. Below is a
test class that visualize some of the issues I have written about.
Please just keep in mind that I am not wrapping invocations of fluent
wait because I want to focus on how it can be used.
import com.google.common.base.Function;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import java.util.concurrent.TimeUnit;
import static org.openqa.selenium.support.ui.ExpectedConditions.*;
public final class ExplicitWaitTest {
private static final int EXPLICIT_WAIT_POOLING = 500;
private static final int EXPLICIT_WAIT_TIMEOUT = 7;
private static final int EXPLICIT_WAIT_CUSTOM_TIMEOUT = 3;
private static final int EXPLICIT_WAIT_PRESENT_TIMEOUT = 1;
private WebDriver driver;
@BeforeTest
public void initialize() {
driver = new ChromeDriver(); // requires system property: -Dwebdriver.chrome.driver=<path to chromedriver.exe>
driver.get("http://docs.seleniumhq.org/");
}
@Test(groups = {"performance"}, timeOut = EXPLICIT_WAIT_TIMEOUT * 1000)
public void customTimeoutTest() {
// withTimeout - setting custom timeout
new FluentWait<WebDriver>(driver)
.pollingEvery(EXPLICIT_WAIT_POOLING, TimeUnit.MILLISECONDS)
.withTimeout(EXPLICIT_WAIT_CUSTOM_TIMEOUT, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class)
.until(new Function<WebDriver, WebElement>() {
@Override
public WebElement apply(WebDriver webDriver) {
return webDriver.findElement(By.xpath("//div[@id='sidebar']"));
}
});
// presenceOfElementLocated - defined in ExpectedConditions
new WebDriverWait(driver, EXPLICIT_WAIT_CUSTOM_TIMEOUT)
.until(presenceOfElementLocated(By.xpath("//div[@id='sidebar']")));
}
@Test(groups = {"performance"}, expectedExceptions = {TimeoutException.class})
public void verifyTest() {
// withTimeout - using shorter timeout for checking for non existing elements
new FluentWait<WebDriver>(driver)
.pollingEvery(EXPLICIT_WAIT_POOLING, TimeUnit.MILLISECONDS)
.withTimeout(EXPLICIT_WAIT_PRESENT_TIMEOUT, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class)
.until(new Function<WebDriver, WebElement>() {
@Override
public WebElement apply(WebDriver webDriver) {
return webDriver.findElement(By.xpath("//div[@id='popup']"));
}
});
// not - defined in ExpectedConditions
new WebDriverWait(driver, EXPLICIT_WAIT_PRESENT_TIMEOUT)
.until(not(presenceOfElementLocated(By.xpath("//div[@id='popup']"))));
}
@Test(groups = {"exceptions"}, expectedExceptions = {TimeoutException.class})
public void exceptionHandlingTest() {
// withMessage - customMessage
// ignoring - exception we don't care about
new FluentWait<WebDriver>(driver)
.pollingEvery(EXPLICIT_WAIT_POOLING, TimeUnit.MILLISECONDS)
.withTimeout(EXPLICIT_WAIT_PRESENT_TIMEOUT, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class)
.withMessage("Popup is not visible")
.until(new Function<WebDriver, WebElement>() {
@Override
public WebElement apply(WebDriver webDriver) {
return webDriver.findElement(By.xpath("//div[@id='popup']"));
}
});
}
@Test(groups = {"reliability"})
public void visibilityTest() {
// ignoring ElementNotVisibleException that will be thrown if we click() on invisible element
new FluentWait<WebDriver>(driver)
.pollingEvery(EXPLICIT_WAIT_POOLING, TimeUnit.MILLISECONDS)
.withTimeout(EXPLICIT_WAIT_TIMEOUT, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class, ElementNotVisibleException.class)
.until(new Function<WebDriver, WebElement>() {
@Override
public WebElement apply(WebDriver webDriver) {
WebElement element = webDriver.findElement(By.xpath("//div[@id='sidebar']"));
element.click();
return element;
}
});
// visibilityOfElementLocated - defined in ExpectedConditions
new WebDriverWait(driver, EXPLICIT_WAIT_TIMEOUT)
.until(visibilityOfElementLocated(By.xpath("//div[@id='sidebar']")))
.click();
}
@Test(groups = {"reliability"})
public void movingTest() {
// ignoring WebDriverException that will be thrown if we click() on moving element
new FluentWait<WebDriver>(driver)
.pollingEvery(EXPLICIT_WAIT_POOLING, TimeUnit.MILLISECONDS)
.withTimeout(EXPLICIT_WAIT_TIMEOUT, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class)
.ignoring(ElementNotVisibleException.class)
.ignoring(WebDriverException.class)
.until(new Function<WebDriver, WebElement>() {
@Override
public WebElement apply(WebDriver webDriver) {
WebElement element = webDriver.findElement(By.xpath("//div[@id='sidebar']"));
element.click();
return element;
}
});
}
@Test(groups = {"conditions"})
public void conditionTest() {
// finding if there is a progressbar and if not searching for another element
new FluentWait<WebDriver>(driver)
.pollingEvery(EXPLICIT_WAIT_POOLING, TimeUnit.MILLISECONDS)
.withTimeout(EXPLICIT_WAIT_TIMEOUT, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class)
.until(new Function<WebDriver, WebElement>() {
@Override
public WebElement apply(WebDriver webDriver) {
if(webDriver.findElements(By.xpath("//div[@id='progress']")).isEmpty()) {
return webDriver.findElement(By.xpath("//div[@id='sidebar']"));
}
return null;
}
});
}
@AfterTest
public void shutdown() {
if (driver != null) {
try {
driver.quit();
driver.close();
} catch (Throwable e) {
// ignore
}
}
}
}
Thank For sharing Valuable Information
ReplyDeleteSelenium Online Training India
Selenium Online Training