Sometimes applications take some time to manipulate data or delay getting the response from server [because of slow internet connection or low application performance], browser takes some time to populate the elements on screen and selenium tries to identify the element before it actually appear on screen, this leads to test failures or unexpected results.
To handle the above situation, selenium provides 2 different types
- Implicit wait
- Explicit wait / WebDriverWait
- Customising explicit wait
Implicit wait
driver object exposes a method implicitly_wait(timeout in seconds)
with parameter as timeout in seconds.
This above method will wait till the specified time to locate an element with specified locator strategy.
If the element is not identified with in the specified time, then it will throw NoSuchElementException
but if the element is identified before the specified time, then selenium will proceed to next line of code and will not wait till the specified time.
for example, you specify the time limit as 30, but element identified in 5sec, then it will not wait till 30sec.
driver.implicitly_wait(30)
def test_Sample1(): driver = webdriver.Chrome("/Users/skpatro/sel/chromedriver") driver.implicitly_wait(30) driver.get("https://qavbox.github.io/demo/delay/")
Note –
- This above method will be only applicable to locate an element.
- Also this implicit wait only need to specify once and is applicable for all elements irrespective of where ever we are identifying / using.
Explicit wait
As we already discussed implicit wait is only applicable for identifying for elements, but if we want to wait based on specific conditions of an element, then we need to use selenium’s explicit wait.
Here is the list of available explicit wait conditions we can use in our script –
Usage –
presence_of_element_located(locator)
from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//p[@id='']")))
This above will wait till 10 seconds as mentioned in WebDriverWait() method, after 10sec also if it’s not able to identify the element with given locator criteria, will throw TimeOutException
We can even write like this
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//p[@id='']"))).click() or send_keys("") //or el = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//p[@id='']"))) el.click() or send_keys("")
Bacially EC.presence_of_element_located will return the webelement, so we can directly perform any element actions on the webDriverWait itself.
For reference, if you go to the implementation –
# expected_conditions.py class presence_of_element_located(object): """ An expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible. locator - used to find the element returns the WebElement once it is located """ def __init__(self, locator): self.locator = locator def __call__(self, driver): return _find_element(driver, self.locator)
Note – each of the methods available, you can go to implementation to know if it returns boolean or web element.
visibility_of_element_located(locator)
Checking that an element is present on the DOM of a page and also visible, should have height & width > 0
Returns webelement, so you can directly perform actions on the WebDriverWait below –
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//p[@id='']")))
text_to_be_present_in_element(locator, text)
checking if the given text is present in the specified element.
WebDriverWait(driver, 10).until(EC.text_to_be_present_in_element((By.XPATH, "//p[@id='']"), "SomeText"))
Above will wait till the element’s text matches to the specified text as 2nd parameter, returns true if the text matches with in the specified time else will throw TimeOutException
Means we can’t perform element actions like click() or send_keys() directly on the above code.
alert_is_present()
WebDriverWait(driver, 10).until(EC.alert_is_present())
This above will wait 10sec or whatever specified time till the alert found, if the specified time is over and alert not found, then will throw TimeOutException
WebDriverWait(driver, 10).until(EC.alert_is_present())
this above will return true if an alert is found.
element_to_be_clickable(locator)
This above will wait till an element is visible and also it’s enabled to perform click operation,
will return true if element is visible and clickable.
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "someXPATH")))
invisibility_of_element(locator)
WebDriverWait(driver, 10).until(EC.invisibility_of_element((By.XPATH, "someXPATH")))
This above will wait till an element with locator specified becomes invisible or disappear from screen.
Example – When you refresh the screen, busy loader appears and we need to wait till the busy loader disappears and then you can continue with your next line of code.
Note –
All the syntaxes of WebDriverWait, I have used By.XPATH, but we can use any available locators like ID / NAME etc…
You can add a dot after EC. and get all available WebDriverWait expectation conditions and explore them by looking into their implementation logic.
Comment your queries if any on the above topic!
Hi there. I could not get presence_of_element to work; it would wait long enough for the xpath or ID to exist but not return the text.
Also: Your written example above uses 2 brackets before the By.XPATH while your video uses one bracket.
Also you are missing a closing bracket at the end of your examples. I have to add an extra bracket for it to work. This is very confusing
This is my code that didnt work: The text is displayed in the web page so the wait works but I get no text variable in the print statement
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, “//p[@id=’two’]”)))
first_text = driver.find_element_by_id(“two”)
print(“first delayed response ” + first_text.text)
This does work: The print statement is complete
first_wait = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, “two”)))
print(“first delayed response ” + first_wait.text)
I have the latest pycharm release version
thanks
Thanks for noticing, I have updated the post with correct brackets.
Try again and let me know if you still get issues?
also you can refer the code here – https://github.com/sunilpatro1985/PageObjectModel_Selenium_Python/blob/master/src/elements/test_selWait.py
Error: WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, ‘//*[@id=”ember44″]/div[2]/div[2]/div/div[2]’)))
File “C:\py\lib\site-packages\selenium\webdriver\support\wait.py”, line 80, in until
raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message:
Seems like the xpath you are using is incorrect, can you recheck and update the xpath?