How to wait for elements in Python Selenium WebDriver
We all know and experimented that Selenium WebDriver can interact with web browser and simulate user actions. User actions could be click, select, type etc.. or combinations of these actions. However most of the user action requires some kind of wait before performing it.
Reasons could be many, including but not limited to below.
- Page is not loaded yet
- Element to interact with is not available in DOM yet
- AJAX is still loading and element will be created after AJAX
- Delay in page response etc…
In modern applications, elements within the page may load at different time intervals even after page is loaded. This makes locating elements difficult; if the element Selenium looking for is not present in the DOM, it will raise NoSuchElementException exception. There should be some kind of delay to wait for these elements. At the same time, this delay should not make test script execution longer.
Using waits, we can wait for an element to be available in DOM. Wait provides some time interval between actions performed like locating element or any other operation with the element.
An implicit wait instructs Selenium WebDriver to poll DOM for a certain amount of time, this time can be specified, when trying to find an element or elements that are not available immediately. The default setting is 0 seconds which means WebDriver will not wait before any operations on element.
Once set, the implicit wait is set for the life of the WebDriver object i.e. all actions will be delayed by given time.
Pass number of seconds to wait as an argument
from selenium import webdriver driver = webdriver.Firefox() driver.implicitly_wait(15) driver.get("http://url") driver.find_element_by_id("id_of_element").click()
Explicit wait is used to specify wait condition for a particular element. Here we define to wait for a certain condition to occur before proceeding further in the code.
There can be instance when a particular element takes more than usual time to load. In that case no need to set a huge time to Implicit wait, as this will make browser to wait for the same time for every element. To avoid that situation explicit wait is used by defining a separate wait time only on the required element.
There are some predefined methods provided that will help your script to wait only as long as required. WebDriverWait in combination with ExpectedCondition is one way this can be accomplished.
Following two packages are required to set explicit wait
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as ec driver = webdriver.Chrome() driver.get("http://url") driver.maximize_window() # wait for element to appear, then hover it wait = WebDriverWait(driver, 10) men_menu = wait.until(ec.visibility_of_element_located((By.XPATH, "//a[@data-tracking-id='men']"))) ActionChains(driver).move_to_element(men_menu).perform() # wait for Fastrack menu item to appear, then click it fastrack = WebDriverWait(driver, 10).until(ec.visibility_of_element_located((By.XPATH, "//a[@data-tracking-id='0_Fastrack']"))) fastrack.click()
This waits up to 10 seconds before throwing a TimeoutException unless it finds the element to return within 10 seconds. WebDriverWait by default calls the ExpectedCondition every 500 milliseconds, which is called poll frequency, until it returns successfully. A successful return is for ExpectedCondition type is Boolean return true or not null return value for all other ExpectedCondition types.
We have the option to change the poll frequency by passing keyword argument ‘poll_frequency’ which accepts values in seconds. Default value is 0.5 second. For instance, lets change poll frequency to 1 second.
wait = WebDriverWait(driver, 10, poll_frequency=1)
The expected_conditions module contains a set of predefined conditions to use with WebDriverWait.