Synchronization/Waits(Implicit and Explicit) Statements in Selenium

In selenium " Synchronization/Waits" play an important role in executing tests. Most of the web applications are developed using Ajax and JavaScript. When a page is loaded by the browser the elements which we want to interact with may load at different time intervals. While executing scripts, sometimes we may face an exception “Element Not Visible Exception“. This exception appears when there is a delay in loading time of the elements which we are interacting. To overcome this issue, we need to use Wait Commands.

Synchronization can be classified into two categories:

1. Unconditional
2. Conditional Synchronization

Unconditional:
we just specify timeout value only. We will make the tool to wait until certain amount of time and then proceed further.

time.sleep(time)
Ex: time.sleep(2)

Note: For this you need import time module.

The main disadvantage is , there is a chances of unnecessary waiting time even though the application is ready.

The advantages are like in a situation where we interact for third party systems like interfaces, it is not possible to write a condition or check for a condition. We have to make the application to wait for certain amount of time by specifying the timeout value.

Conditional Synchronization:
We specify a condition along with timeout value, so that tool will wait to check for the condition and then come out if nothing happens.

It is very important to set the timeout value in conditional synchronization, because the tool should proceed further instead of making the tool to wait for a particular condition to satisfy.

Different Types of Selenium Synchronization /Wait Commands are:
1)   Implicit Wait
2)   Explicit Wait 

Implicit Wait

The implicit wait tells the WebDriver to wait for certain amount of time before it throws an exception. Once we set the time, WebDriver will wait for the element based on the time we set before it throws an exception. The default setting is 0 (zero). We need to set some wait time to make WebDriver to wait for the required time.

Note: Implicit Wait is in place for the entire time the browser is open. Time taken to search all the elements are based on the time fixed for the implicit wait.

Syntax:
driver.implicitly_wait(timeout)
Ex: driver.implicitly_wait(20)# seconds

Implicit Wait time is applied to all the elements in the script until modified By default, the implicit wait time set is 0.

Scenario :
Invoke Google Chrome browser.
Enter UserName and Password
Click on the Login button.
Verify the Window Title
Close the browser

from selenium import webdriver
from time 
chromePath="C:\\resources\\executables\\chromedriver.exe" 
driver=webdriver.Chrome(executable_path=chromePath)
driver.get("http://newtours.demoaut.com")
driver.find_element_by_name("userName").send_keys("hello")
driver.find_element_by_name("password").send_keys("hello")
driver.find_element_by_name("login").click()
driver.implicitly_wait(30) # seconds
print(driver.title)
driver.close()

It tells the Web driver to poll the DOM for a certain amount of time , here for 30 seconds, when trying to find an element or elements if they are not immediately available

Explicit Wait
The explicit wait is used to tell the Web Driver to wait for certain conditions (Expected Conditions) or the maximum time exceeded before throwing an exception.
The explicit wait is an intelligent kind of wait, but it can be applied only for specified elements. Explicit wait gives better options than that of an implicit wait as it will wait for dynamically loaded Ajax elements.
In worst case time.sleep(), which sets the condition to an exact time period to wait. There are some convenience methods provided that help you write code that will wait only as long as required. Once we declare explicit wait we have to use "ExpectedCondtions"
WebDriver introduces classes/modules like WebDriverWait and ExpectedConditions to enforce Explicit waits into the test scripts.

Ex:
wait = WebDriverWait (driver, 15);
wait. until(ExpectedConditions.presenceOfElementLocated(ElementLocator));

Here the webDriver instance will wait until the condition specified is met i.e. the presence Of Element located by the ElementLocator with the maximum wait time of 15 seconds after which if the condition is still not met than it will throw exception.

If you want to use explicit wait you should import below two modules

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions

Scenario :
Invoke Google Chrome browser.
Enter UserName and Password
Click on the Login button.
Wait for Continue button to be visible after page load
Close the browser

Script: 
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
chromePath="C:\\resources\\executables\\chromedriver.exe"
driver=webdriver.Chrome(executable_path=chromePath)
driver.get(
"http://newtours.demoaut.com")
driver.find_element_by_name(
"userName").send_keys("hello")
driver.find_element_by_name(
"password").send_keys("hello")
driver.find_element_by_name(
"login").click()
wait=WebDriverWait(driver,
15)
wait.until(EC.visibility_of_element_located((By.XPATH,
"//input[@type='image' and @name='findFlights']")))
print(driver.title)
driver.close()

This waits up to 15 seconds before throwing a TimeoutException unless it finds the element to return within 15 seconds. WebDriverWait by default calls the ExpectedCondition every 500 milliseconds, which is called poll frequency, until it returns successfully.

Explicit wait you can write like this also

eleVisiblity=EC.visibility_of_element_located((By.XPATH,"//input[@type='image' and @name='findFlights']"))
wait=WebDriverWait(driver,
15)
wait.until(eleVisiblity)

The expected_conditions module contains a set of predefined conditions to use with WebDriverWait.

title_is
title_contains
presence_of_element_located
visibility_of_element_located
visibility_of
presence_of_all_elements_located
text_to_be_present_in_element
text_to_be_present_in_element_value
frame_to_be_available_and_switch_to_it
invisibility_of_element_located
element_to_be_clickable
staleness_of
element_to_be_selected
element_located_to_be_selected
element_selection_state_to_be
element_located_selection_state_to_be
alert_is_present

Custom Wait Conditions
You can also create custom wait conditions when none of the method matches your requirements. A custom wait condition can be created using a class with __call__ method or using lambda function which returns False/TimeoutException when the condition doesn’t match.

Scenario :
Invoke Google Chrome browser.
Enter UserName and Password
Click on the Login button.
Wait for Continue button after page load
Close the browser 
Note: using lambda function. 
Script:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

import time
chromePath=
"C:\\resources\\executables\\chromedriver.exe"
driver=webdriver.Chrome(executable_path=chromePath)
driver.get(
"http://newtours.demoaut.com")
driver.find_element_by_name(
"userName").send_keys("hello")
driver.find_element_by_name(
"password").send_keys("hello")
driver.find_element_by_name(
"login").click()
wait=WebDriverWait(driver,
15)
wait.until(
lambda s: s.find_element_by_xpath("//input[@type='image' and @name='findFlights']").get_attribute("name")=='findFlights')

print(driver.title)
driver.close()

In the above example webdriver will wait for 15 seconds until the “name” attribute matches for the element else it will throw TimeoutException. 
A custom wait condition can be created using a class with __call__ method which returns False when the condition doesn’t match. 
Scenario :
Invoke Google Chrome browser.
Enter UserName and Password
Click on the Login button.
Wait for Continue button after page load
Close the browser
Note: using __call__ function. 
The ”elementWaitStatement” function has to be written as:
class elementWaitStatement:
   
def __init__(self,loc,attribute,value):
       
self._loc=loc
       
self._attribute=attribute
       
self._attr_value=value

   
def __call__(self, driver):
        ele=driver.find_element_by_xpath(
self._loc)
        actAttributeValue=ele.get_attribute(
self._attribute)
       
if actAttributeValue==self._attr_value:
           
return actAttributeValue
       
else:
           
return False

the above script save it as elementWait.py

Script:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from elementWait import elementWaitStatement
import time
chromePath="C:\\resources\\executables\\chromedriver.exe"
driver=webdriver.Chrome(executable_path=chromePath)
driver.get(
"http://newtours.demoaut.com")
driver.find_element_by_name(
"userName").send_keys("hello")
driver.find_element_by_name(
"password").send_keys("hello")
driver.find_element_by_name(
"login").click()
wait=WebDriverWait(driver,
15)
eleValue=wait.until(elementWaitStatement("//input[@type='image' and @name='findFlights']","name","findFlights")) 
print(eleValue)
driver.close()

In the above example webdriver will wait for 15 seconds until the “name” attribute matches for the element else it will return false. 
Note: you should Import “elementWaitStatementfrom elementwait, it is custom define wait statement.
Difference between Implicit Wait Vs Explicit Wait
Implicit Wait
1)   Implicit Wait time is applied to all the elements in the script.
2)   we need not specify "anyExpectedConditions" on the element to be located.
3)   It is recommended to use when the elements are located with the time frame specified in implicit wait.
Explicit Wait
1)   Explicit Wait time is applied only to those elements which are intended by us.
2)   In Explicit Wait, we need to specify "ExpectedConditions" on the element to be located.
3)   It is recommended to use when the elements are taking long time to load and also for verifying the property of the element.

Comments