Its said, “time has a wonderful way of showing us what really matters”. But waiting until everything materializes is equally important. These days, web pages are mostly developed using javascript and ajax techniques. As a result, different elements on the page load at different times. When we automate our manual tests using selenium WebDriver and run them as test suites, it’s time for you to watch out as you might bump into Selenium’s weird behavior.
Your test case runs successfully and works as expected when you step through it one line at a time but running as a suite/batch, it might fail. Scratching your head to understand the reason behind this? Let’s dive in for more!
When we use driver.get(“url_we_wish_to_access”), driver.navigate().to(“url”) or click on a hyperlink etc., these invocations start the page to load and return before that loading activity is even complete. So, if the page’s load thread hasn’t populated the web element yet and you try to find it using driver.findElement(“locating_strategy”), all that you get is an exception viz., NoSuchElementException, ElementNotVisibleException etc.
All this means that we have to find a way to tell Selenium, that we would like it to wait for a certain amount of time or until the web element becomes accessible/clickable/displayed before throwing that dreaded exception. There, there, don’t panic. I see some beads of sweat trickling down your forehead there! So, how to make this stress our own version of popeye’s spinach? All thanks to Implicit, Explicit and Fluent Waits.
Time to visit each of these waits one after another.
Implicit Wait
It is important to understand that we locate web elements in WebDriver using findElement or findElements command (The posts to follow will cover this topic along with various locating strategies in detail). Hence, when trying to find a particular web element on the page, if it is not immediately available, implicit wait tells WebDriver to poll the DOM for specified amount of time. Test execution will continue in case the element is found within the specified wait time. If not then NoSuchElementException is thrown.
Below is a code snippet with implicit wait command for better understanding,
@Before
public void setUp() throws Exception{
// Selenium version 3 beta releases require system property set up
System.setProperty("webdriver.gecko.driver", "E:\\Selenium\\geckodriver-v0.10.0-win64\\geckodriver.exe");
// Create a new instance for the class FirefoxDriver
// that implements WebDriver interface
driver = new FirefoxDriver();
// Implicit wait for 3 seconds
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
// Assign the URL to be invoked to a String variable
baseUrl = "https://www.google.com";
pageTitle = "";
expectedTitle = "Google";
}
As highlighted, the syntax of using an implicit wait is,
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
Implicit wait takes two parameters. In this example, we have the first parameter as 3 which is the time it has to wait and the second parameter, TimeUnit.SECONDS. This is the time measurement. It can be specified as DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS, MICROSECONDS, NANOSECONDS etc.
Also, on typing this statement, a squiggly line appears below ‘TimeUnit’. Upon hovering, eclipse will suggest all possible quick fixes. Click on the first fix that suggests to import java.util.concurrent.TimeUnit package.
- Implicit Wait requires only one time initialization. Once set, it will apply for the life of the WebDriver object instance. In other words, it will be in place for the entire time the browser is open. So, WebDriver will wait for that additional time before throwing an exception for all findElement and findElements
- The default time setting is 0.
- Implicit Wait affects findElement(s) only, it does not affect other WebDriver methods such as, driver.getCurrentUrl() etc.
- ‘NoSuchElementException’ alone is not very helpful in most cases especially when debugging. We might want to customize this error message with more information such as capturing a screenshot or adding more details etc. It is possible to do so with a try-catch block around each findElement(s) invocation but that is not our goal with Implicit Wait as it is a global one time setting.
- Due to a huge amount of JavaScript, there can be some weird scenarios. Even though the element is located in the DOM, it may not be clickable or displayed or enabled immediately. As a result we might see ElementNotVisibleException, WebDriverException, StaleElementReferenceException
- Since different elements may load at different times, we might feel persuaded to set the wait time to a high value (or equivalent to the load time of the slowest web element) such as 20 seconds or so. Our justification to this would be, ‘anyway all elements will load faster than this time and test will continue as expected’. But do you even guess that performance-wise this approach is not a good idea? Let me give you a couple cases here for better insight,
Case 1: If you wish you locate an element but continue with the test irrespective of the result.
Case 2: If you just need to verify absence of an element such as waiting for an alert box to appear and closing it. Even then WebDriver will have to wait until timeout, i.e. 20 seconds in this case. This will cause a great impact when run in a huge test suite.
To overcome some of the disadvantages of Implicit Wait, we have Explicit Wait to our rescue! But considering that our brains can only take up so much at a time, I am reserving this topic for our next post.
See you soon! Have a wait-worthy day!