Wait Interface in Selenium

Wait is the generic interface, which makes selenium to wait for a particular time with the associated event. Events like elements to be click-able, element to present.

Wait interface present under org.openqa.selenium.support.ui package, FluentWait, and WebdriverWaitimplements Wait interface.

Until Method in WebdriverWait :

until is an abstract method present in the Wait interface, whichever driver implements Webdriver the also must implement the Wait interface.

This means browser classes (FirefxDriver, ChromeDriver...) must implement methods present in Wait and Webdriver interfaces.

until method accepts ExpectedConditions values as a parameter, the class must wait till the given condition neither becomes null nor false when they implement until method. So until methods implementation must not have return type as void.

FluentWait class implements Wait Interface and WebdriverWait class extends FluentWait class, this is called as a multi-level inheritance in java.

wait-fluent-implicit-selenium-webdriver

Explicitly Wait in Selenium

Fluent Wait in Selenium

FluentWait class implements the Wait interface in selenium, FluentWait object defines the maximum amount of time to wait for a condition. Below is the example for a common way of using Fluent Wait

// create object for FluentWait class
FluentWait fw = new FluentWait(driver);
// max time limit is 30 seconds
fw.withTimeout(30, TimeUnit.SECONDS);


Users can configure the frequency with which to check the condition.

// polls once in every 5 seconds
fw.pollingEvery(5, TimeUnit.SECONDS);


Users may configure the FluentWait to ignore specific types of exceptions while waiting for the condition.

// ignore the Exception
fw.ignoring(NoSuchElementException.class);


Users can configure the error message to display in case of TimeoutException occurs.

// custom message to show if exception occurs
fw.withMessage("Time exceeded");

Mis-Conception : You might have heard that FluentWait is another kind of WebdriverWait/ExplicitWait, but the reality is, WebdriverWait is another kind of FluentWait

implicit-wait-selenium

Methods / Features of Fluent Wait in selenium

These are the methods present in the FluentWait, we may not use all of the methods in our practical use, but we can use it reap the maximum benefit.

FluentWait fw = new FluentWait(driver);

withTimeout :

This method sets the time limit for Fluent wait, i.e. how much time to wait for a condition when Fluent wait is used. withTimeout method accepts two parameters the first parameter is the amount of time, and the second parameter is what is the TimeUnit for the amount of time. TimeUnit could be from Nano-seconds to Days.

// maximum time limit is 1 minute
fw.withTimeout(1, TimeUnit.MINUTES);

pollingEvery :

frequency of polling the webpage for particular element/condition, if give 10 Seconds FluentWait polls the webpage once in ever 10 seconds. Default polling time in FluentWait is 500 Milli-seconds

// polls once in every 5 seconds
fw.pollingEvery(5, TimeUnit.SECONDS);

ignoring :

ignoring method makes the fluent wait to ignore the particular exception threw during the wait time, in below line Fluent wait ignores if NoSuchElementException and FluentWait continues to poll for the condition, ignoring method is overloaded, and it can accept two Exceptions as well

fw.ignoring(NoSuchElementException.class);
//overloaded method
fw.ignoring(NoSuchElementException.class, NoSuchWindowException.class);

ignoreAll :

ignores a list of exceptions that occur during the wait time, we have to pass Collection type parameter to this method; collection type could be List, Set, Queue.

// create a array list to exceptions
List allExceptions = new ArrayList();
// add few exception to the list
allExceptions.add(NoSuchElementException.class);
allExceptions.add(ElementNotVisibleException.class);
allExceptions.add(NoSuchFrameException.class);
// ignore all the exception in the list
fw.ignoreAll(allExceptions);

withMessage :

given string message will be displayed at the final exception.

// custom message to show if exception occurs
fw.withMessage("THIS IS EXCEPTION MESSAGE");

timeoutException :

timeoutException is a protected method of the FluentWait class; we have to override this method to raise our own messages.

@override
public RuntimeException timeoutException(String message, Throwable lastException) {
	throw new NoSuchFrameException(message, lastException);
  }

until :

until method recursively calls ( calls the self, i.e. same function ), it's input value to the given function until the function returns neither null nor false based on the polling interval, until method throws an exception if the method returns a null or false after the time limit.

This particular step will be completed when the functions return type is true or not null, until method accepts Predicate or Function Interface types

until(java.util.function.Function<? super T,V> isTrue)

until method's Termination :

until methods in FluentWait get terminated on the below scenarios.

  • When the apply function returns a value other than null or false
  • When apply function throws an un-ignored( We provide the ignoring Exception(s) ) exception
  • When the time limit reached
  • When a current thread is interrupted by other threads

Page Load Timeout in Selenium

Function Interface with FluentWait in Webdriver

If you keenly notice .until() method in the accepts Function Interface type or Predicate Interface type.

Function Interface:

Function Interface helps the user to implement their own implementation for the apply method, which is nothing but what kind of operation you want to perform like check whether an element present, check whether alert present, check whether the title is changed so on...

Function interface is a generic interface, and it is represented as Function<T, R> where T is the type of object passed to apply method and R is the type of object returned by the apply function.

If we are implementing the Function interface, we must provide an implementation for the abstract apply() method present in the Function Interface.

Function can return any value, that we mentioned in the Function interface generic.

Skeleton Example for Function Interface:

Function<T, R> function = new Function()
	{
		public R apply(T arg0) {
			return r;
		}
	}


T apply method's parameter type, and it could be WebDriver, WebElement, String; basically it could be anything.

R apply method's return type, and it could be WebDriver, WebElement, String; basically, it could be anything.

Practical Example :
1. We are accepting WebDriver type parameter to the apply method and returning WebElement type object.

2. We are overriding the apply method to find the element and return the element

If you keenly notice .until() method in the accepts Function Interface type or Predicate Interface type.

Function Interface:
Function Interface helps the user to implement their own implementation for the apply method, which is nothing but what kind of operation you want to perform like check whether an element present, check whether alert present, check whether the title is changed so on.

Function interface is a generic interface, and it is represented as Function<T, R> where T is the type of object passed to apply method and R is the type of object returned by the apply function.

If we are implementing Function interface, we must provide implementation for the abstract apply() method present in the Function Interface.

Function can return any value, that we mentioned in the Function interface generic.

Skeleton Example for Function Interface:

Function<T, R> function = new Function()
	{
		public R apply(T arg0) {
			return r;
		}
	}


T apply method's parameter type, and it could be WebDriver, WebElement, String; basically, it could be anything..

R apply method's return type, and it could be WebDriver, WebElement, String; basically, it could be anything.

Practical Example :
1. We are accepting WebDriver type parameter to the apply method and returning WebElement type object.

2. We are overriding the apply method to find the element and return the element

WebElement feelingLuckyButton = (WebElement) fw.until(new Function<WebDriver, WebElement>() {
	public WebElement apply(WebDriver driver) {
		System.out.println("Polling for feeling Lucky Button");
		// return the button as webelement
		return driver.findElement(By.xpath("//input[@name='btnI-fail']"));
	}
});

Database Testing in Selenium

Predicate Interface with FluentWait in Selenium Webdriver

Predicate Interface : Depreciated from Selenium version 3.2.0 onwards

Predicate interface is almost the same as Function Interface; the only difference is Predicate return only boolean Object whereas Function Interface returns any value.

Predicate Interface accepts generic type as parameter (any value), We have to implement the test()method from the Predicate Interface.

Predicate<T> pr = new Predicate<T>() {
		@Override
		public boolean test(T arg0) {
			// TODO Auto-generated method stub
			return boolean;
		}
	};


T is the Generic, and it could be anything, like WebElement, Webdriver, String or anything.

A practical example for Predicate Interface:

Below example checks Whether the given page title is 'Google' or not and it waits till the page title becomes 'Google', when the test method returns 'false' the same test method will be recalled, till return value becomes true or the time limit reaches.

boolean pageTitle = fw.until(new Predicate<WebDriver>() {
		@Override
		public boolean test(WebDriver arg0) {
			// check whether URL of the page contains 'doodle'
			if(arg0.getTitle().equals("Google")){
				return true;
			}
			else{
				// return false if the URL of the page does not contains 'doodle'
				return false;
			}
		}
	});

API testing with selenium

Static Method Along with Until in FluentWait

We can pass static and non-static methods to the until, until method calls these methods until the methods return neither false nor null.

Until with static method :

1. Create a class called CustomFluent

2. Create a static method waitTillURLContains; this method will be used by FluentWait to wait till URL contains a particular String or till time expires.

3. waitTillURLContains accept only the Webdriver parameter.

4. Write condition to check if the URL contains doodle string, return true if it contains otherwise return false.

static boolean waitTillURLContains(WebDriver arg) {
		if(arg.getTitle().equals("Googl-e")){
			System.out.println("URL contains 'doodle'");
			return true;
		}else{
			System.out.println("URL does not contain 'doodle'");
			return false;
		}
	}


5. Create the browser object and navigate to the google page.

6. Create an object for FluentWait and register the polling time(10 seconds) and the total timeout(60 seconds).

7. Click the I'm Feeling Lucky button

8. Call the waitTillURLContains method to check whether the URL contains 'doodle' or not. We know that until method recalls the given method repeatedly with polling frequency until it receives a true or not null object from the given function.

// wait till the URL contains 'doodle' string
wait.until(AA::waitTillURLContains);


9. If you notice on above program we have used :: to call a method. We normally use class name(CustomFluent) .(dot) method name for the methods, for static method we use ClassName.MethodName(), for non-static methods we use classObject.MethodName().

When we use .(dot) notation, the method returns the exact return type. When we call a method using ::, method does not explicitly return any type, during runtime, the return type is decided.

import org.openqa.selenium.support.ui.FluentWait;
public class CustomFluent {

	static boolean waitTillURLContains(WebDriver arg) {
		if(arg.getTitle().equals("Googl-e")){
			System.out.println("URL contains 'doodle'");
			return true;
		}else{
			System.out.println("URL does not contain 'doodle'");
			return false;
		}
	}

	public static void main(String[] args) throws InterruptedException {
		// set chrome driver exe path
		System.setProperty("webdriver.chrome.driver", "C:/~/chromedriver.exe");

		// create object for chrome browser
		WebDriver driver = new ChromeDriver();

		// navigate to google
		driver.get("https://google.com/");

		//create Fluent Wait object
		FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver);

		// set the polling frquency as 10 seconds
		wait.pollingEvery(10,  TimeUnit.SECONDS);

		// set total timeout as 60 seconds
		wait.withTimeout(60, TimeUnit.SECONDS);

		// ignore the NoSuchElementException Exception if occurs
		wait.ignoring(NoSuchElementException.class);

		//click the Feeling lucky button
		driver.findElement(By.xpath("//input[@id='btnK']")).click();

		// wait till the URL contains 'doodle' string
		wait.until(CustomFluent::waitTillURLContains);
	}
}


Similar way we can also access the non-static method using object reference like below

//create object for the CustomFluent class
CustomFluent abc = new CustomFluent();
// wait till the URL contains 'doodle' string
wait.until(abc::waitTillURLContains);

Docker with Selenium

FluentWait with PASS Scenario

Let's test the Fluent wait with pass scenario, Click the Google's Feeling Lucky button with Fluent button.

1. Create a browser instance/object and navigate to Url.

2. Create fluent wait object

// create object for FluentWait class
FluentWait fw = new FluentWait(driver);


3. Set the Fluent wait timeout as 30 seconds

// max time limit is 30 seconds
fw.withTimeout(30, TimeUnit.SECONDS);


4. Check whether an element is present on the webpage once in every 5 seconds

// polls once in every 5 seconds
fw.pollingEvery(5, TimeUnit.SECONDS);

5. Ignore if selenium throws NoSuchelementException, because element is not there

// ignore the Exception
fw.ignoring(NoSuchElementException.class);


6. Implement Function interface with until method, we can also implement predicate in until method. Please refer Function and Predicate Section for more details about them.

// create a the function which finds the element and returns
WebElement feelingLuckyButton = (WebElement) fw.until(new Function<WebDriver, WebElement>() {


7. Return the WebElement (Feeling Lucky Button ) from the apply button.

// return the button as webelement
return driver.findElement(By.xpath("//input[@name='btnI-']"));


8. Click the returned element

// click feeling lucky button
feelingLuckyButton.click();


Complete program for FluentWait with pass scenario

public class CustomImplicitWait {

	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		// set chrome driver exe path
		System.setProperty("webdriver.chrome.driver", "C:/~/chromedriver.exe");
		WebDriver driver = new ChromeDriver();
		driver.get("https://google.com");
		// create object for FluentWait class
		FluentWait fw = new FluentWait(driver);
		// max time limit is 30 seconds
		fw.withTimeout(30, TimeUnit.SECONDS);
		// polls once in every 5 seconds
		fw.pollingEvery(5, TimeUnit.SECONDS);
		// ignore the Exception
		fw.ignoring(NoSuchElementException.class);

		// custom message to show if exception occurs
		fw.withMessage("THIS IS EXCEPTION MESSAGE");

		// create a the function which finds the element and returns
		WebElement feelingLuckyButton = (WebElement) fw.until(new Function<WebDriver, WebElement>() {
			public WebElement apply(WebDriver driver) {
				System.out.println("Polling for feeling Lucky Button");
				// return the button as webelement
				return driver.findElement(By.xpath("//input[@name='btnI']"));
			}
		});
		System.out.println("clicking feeling lucky button");
		// click feeling lucky button
		feelingLuckyButton.click();
	}
}

Cucumber With Selenium

Fluent Wait with FAILURE scenario

In this, we are going to learn what happens when fluent wait failure occurs, lets modify the above program.

1. Change the locator from xpath("//input[@name='btnI-']") to xpath("//input[@name='btnI-fail']"), added -fail in the XPath which is not matching with any element on google page

2. Create a Fluent Wait object and set the polling time and ignore it.

3. Provide custom message for the exception, so that when there is no element this message will be Shown along with an exception

// custom message to show if exception occurs
fw.withMessage("THIS IS EXCEPTION MESSAGE");

Complete program for Fluent Wait failure scenario

public class CustomImplicitWait {

	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		// set chrome driver exe path
		System.setProperty("webdriver.chrome.driver", "C:/~/chromedriver.exe");
		WebDriver driver = new ChromeDriver();
		driver.get("https://google.com");
		// create object for FluentWait class
		FluentWait fw = new FluentWait(driver);
		// max time limit is 30 seconds
		fw.withTimeout(30, TimeUnit.SECONDS);
		// polls once in every 5 seconds
		fw.pollingEvery(5, TimeUnit.SECONDS);
		// ignore the Exception
		fw.ignoring(NoSuchElementException.class);

		// custom message to show if exception occurs
		fw.withMessage("THIS IS EXCEPTION MESSAGE");

		// create a the function which finds the element and returns
		WebElement feelingLuckyButton = (WebElement) fw.until(new Function<WebDriver, WebElement>() {
			public WebElement apply(WebDriver driver) {
				System.out.println("Polling for feeling Lucky Button");
				// return the button as webelement
				return driver.findElement(By.xpath("//input[@name='btnI-fail']"));
			}
		});
		System.out.println("clicking feeling lucky button");
		// click feeling lucky button
		feelingLuckyButton.click();
	}
}


Analysis of Fluent Wait program's run fluent-wait-selenium-webdriver

Please refer above image for number details.

  • org.openqa.selenium.TimeoutException is thrown by webdriver, as we have not written any custom exception the default TimeoutException is thrown when there is no matching element
  • THIS IS EXCEPTION MESSAGE exception detail contains our custom message, that we have set
  • tried for 30 second(s) shows what is the maximum time that fluent wait waited for the matching element
  • with 5 SECONDS interval shows the frequency of polling, we have 5 seconds frequency for 30 seconds which means it tried for 6 times along with default time, at 0'th moment fluent wait tries to find the element but if the element is not present, it tries after 5 seconds(for 6 times), so there will be 7 attempts, Because of which there 7 polling statements.
  • org.openqa.seleniumNoSuchElementException is the actual root exception, which occurred after 30 seconds, this exception turned on the TimeoutException

Take Page & Element Screenshot, Compare Screenshots in selenium

Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions