Waits and Synchronization

Context:

Whenever we hit a URL in a browser, the request is submitted to the server and it returns back with resources (response object, headers, javascript etc.). Ultimately it is the browser engine that parses the response from server and displays the elements like text fields, buttons, links and so on. In other works as defined by W3C, the DOM (document object model) dictates how the content gets displayed on browser. Every time a user performs an operation on the browser, one of the following (not limited to) happens:

1) The request goes all the way to server and entire DOM is refreshed when response comes back

2) The request hits the server and only partial DOM gets refreshed (ajax requests or asynchronous javascript calls)

3) The request is processed on the client side itself by javascript functions

So if we think about the overall workflow, there needs a certain synchronization that happens between the client(aka. browser) and the server (the url)

How is it related to Test Automation?

If we peruse a little deeper, the operations we do on browser has to be aligned with how the server or the web app responds. For example, if I hit a website and it takes 5 seconds for the website to respond, I would have to wait for at least 5 seconds in my script before doing further operations. So every operation is governed by a timeout after which I report a failure in my script and ultimately a defect is a possibility. So while writing my test Automation scripts, I have to have mechanisms to do “Waits” and define “timeouts”, not only at the page level, but also at the element level and sometimes. 

But What am I really waiting for ?

The following will help explain each of the wait scenarios. In the java side of Selenium, you will find an additional wait called FluentWait in addition to the ImplicitWait and ExplicitWait mechanisms we discuss here. So its really ImplicitWait vs ExplicitWait vs FluentWait is what some folks might be looking for. 

With FluentWait , one can specify how frequently selenium should poll for the element. In general, by default selenium polls every 500 ms, but with FluentWait, we can control that. I haven’t found a great need for FluentWait i.e. needing to poll lesser than 500ms so far, so selenium/watir on ruby side NOT having that as an api is totally fine. On the other hand, if we have to implement such a Waiter, we can implement if need be.

Page Load

Page load timeout as the name suggests is setting the max. time until which we will wait for the page to load. By default the page load is infinite

Script Timeout

The script timeout is generally used with ajax waiting commands. For example as seen below, we are setting a max. timeout of 5 seconds for execute_script() method. That means, the webdriver will wait for a max. of 5 seconds for the script to execute and return. If the script execution takes more than 5 seconds, a TimeOut Error is thrown and the execution halts.

Implicit Wait

Implicit Wait is the max. wait time we want to wait for element to move forward with the operation on the element. Implicit timeout applies to all WebElements once set i.e. it is a global setting. It is advised NOT to mix up implict and explicit timeouts.

Explicit Wait (using exists,present,visible)

Explicit waits are the best practice waits to be used in automation scripts especially since modern web apps have different timeouts on different parts of web page. Explicit timeouts are also a great set of functionality to help us get granular and wait for different elements for different waiting times.

Returns true based on if the element exists, present or visible

Explicit Wait (when_present(timeout))

When we call when_present(timeout) method on an element, it returns the WebElement if found within the timeout, otherwise raises a NoElementError

Explicit Wait (wait_until_present)

wait_until_present(timeout) returns true if the element is found within timeout, otherwise raises a Noelementerror

Explicit Wait (Wait.until)

Most likely the above waits should suffice your needs, in case it doesn’t and you would like to wait on something else, Watir provides a generic WebDriver::Wait.until(timeout) method for any custom wait

Entire Cucumber Scenario (Waits.feature)

Step Definitions (Waits.rb)