Selenium waitForElement

Question:

How do I write the function for Selenium to wait for a table with just a class identifier in Python? I’m having a devil of a time learning to use Selenium’s Python webdriver functions.

Asked By: Breedly

||

Answers:

I have made good experiences using:

  • time.sleep(seconds)
  • webdriver.Firefox.implicitly_wait(seconds)

The first one is pretty obvious – just wait a few seconds for some stuff.

For all my Selenium Scripts the sleep() with a few seconds (range from 1 to 3) works when I run them on my laptop, but on my Server the time to wait has a wider range, so I use implicitly_wait() too. I usually use implicitly_wait(30), which is really enough.

An implicit wait is to tell WebDriver to poll the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object instance.

Answered By: naeg

Use Wait Until Page Contains Element with the proper XPath locator. For example, given the following HTML:

<body>
  <div id="myDiv">
    <table class="myTable">
      <!-- implementation -->
    </table>
  </div>
</body>

… you can enter the following keyword:

Wait Until Page Contains Element  //table[@class='myTable']  5 seconds

Unless I missed something, there is no need to create a new function for this.

Answered By: jro

In case this helps …

In the Selenium IDE, I added …
Command: waitForElementPresent
Target: //table[@class=’pln’]

Then I did File>Export TestCase As Python2(Web Driver), and it gave me this …

def test_sel(self):
    driver = self.driver
    for i in range(60):
        try:
            if self.is_element_present(By.XPATH, "//table[@class='pln']"): break
        except: pass
        time.sleep(1)
    else: self.fail("time out")
Answered By: jcfollower

I implemented the following for python for wait_for_condition since the python selenium driver does not support this function.

def wait_for_condition(c):
for x in range(1,10):
    print "Waiting for ajax: " + c
    x = browser.execute_script("return " + c)
    if(x):
        return
    time.sleep(1)

to be used as

Wait that an ExtJS Ajax call is not pending:

wait_for_condition("!Ext.Ajax.isLoading()")

A Javascript variable is set

wait_for_condition("CG.discovery != undefined;")

etc.

Answered By: Deven Kalra

From the Selenium Documentation PDF :

import contextlib
import selenium.webdriver as webdriver
import selenium.webdriver.support.ui as ui

with contextlib.closing(webdriver.Firefox()) as driver:
    driver.get('http://www.google.com')
    wait = ui.WebDriverWait(driver,10)
    # Do not call `implicitly_wait` if using `WebDriverWait`.
    #     It magnifies the timeout.
    # driver.implicitly_wait(10)  
    inputElement=driver.find_element_by_name('q')
    inputElement.send_keys('Cheese!')
    inputElement.submit()
    print(driver.title)

    wait.until(lambda driver: driver.title.lower().startswith('cheese!'))
    print(driver.title)

    # This raises
    #     selenium.common.exceptions.TimeoutException: Message: None
    #     after 10 seconds
    wait.until(lambda driver: driver.find_element_by_id('someId'))
    print(driver.title)
Answered By: unutbu

You could always use a short sleep in a loop and pass it your element id:

def wait_for_element(element):
     count = 1
     if(self.is_element_present(element)):
          if(self.is_visible(element)):
              return
          else:
              time.sleep(.1)
              count = count + 1
     else:
         time.sleep(.1)
         count = count + 1
         if(count > 300):
             print("Element %s not found" % element)
             self.stop
             #prevents infinite loop
Answered By: TheDawg

Selenium 2’s Python bindings have a new support class called expected_conditions.py for doing all sorts of things like testing if an element is visible. It’s available here.

NOTE: the above file is in the trunk as of Oct 12, 2012, but not yet in the latest download which is still 2.25. For the time being until a new Selenium version is released, you can just save this file locally for now and include it in your imports like I’ve done below.

To make life a little simpler, you can combine some of these expected condition methods with the Selenium wait until logic to make some very handy functions similar to what was available in Selenium 1. For example, I put this into my base class called SeleniumTest which all of my Selenium test classes extend:

from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
import selenium.webdriver.support.expected_conditions as EC
import selenium.webdriver.support.ui as ui

@classmethod
def setUpClass(cls):
    cls.selenium = WebDriver()
    super(SeleniumTest, cls).setUpClass()

@classmethod
def tearDownClass(cls):
    cls.selenium.quit()
    super(SeleniumTest, cls).tearDownClass()

# return True if element is visible within 2 seconds, otherwise False
def is_visible(self, locator, timeout=2):
    try:
        ui.WebDriverWait(driver, timeout).until(EC.visibility_of_element_located((By.CSS_SELECTOR, locator)))
        return True
    except TimeoutException:
        return False

# return True if element is not visible within 2 seconds, otherwise False
def is_not_visible(self, locator, timeout=2):
    try:
        ui.WebDriverWait(driver, timeout).until_not(EC.visibility_of_element_located((By.CSS_SELECTOR, locator)))
        return True
    except TimeoutException:
        return False

You can then use these easily in your tests like so:

def test_search_no_city_entered_then_city_selected(self):
    sel = self.selenium
    sel.get('%s%s' % (self.live_server_url, '/'))
    self.is_not_visible('#search-error')
Answered By: Dave Koo

Hopefully this helps

from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By   


driver = webdriver.Firefox()
driver.get('www.url.com')

try:
    wait = driver.WebDriverWait(driver,10).until(EC.presence_of_element_located(By.CLASS_NAME,'x'))
except:
    pass
Answered By: John LeComte

If I don’t know something about selenium command, I use selenium web idea RC with firefox. You can choose and add command in the combobox and when finish your test case after you can export the test code different language. like java, ruby, phyton, C#, etc..

Answered By: onder.diri

easier solution:

    from selenium.webdriver.common.by import By    
    import time

    while len(driver.find_elements(By.ID, 'cs-paginate-next'))==0:
        time.sleep(100)
Answered By: Ben

You can modify this function to all type of elements. The one below is just for the class element:

Where “driver” is the driver, “element_name” is the class name you are looking for, and “sec” is the maximum amount of seconds you are willing to wait.

def wait_for_class_element(driver,element_name,sec):

    for i in range(sec):        
        try:
            driver.find_element_by_class_name(element_name)
            break
        except:        
            print("not yet")
            time.sleep(1)
Answered By: Diego Orellana

I found an easier way to build this using a custom function, which is recursive in nature

from selenium import webdriver
import time

def wait_element_by_id(id_value):
    try:
        elem = driver.find_element_by_id(id_value)
    except:
        time.sleep(2)
        print 'Waiting for id '+id_value
        wait_element_by_id(id_value)

You can replace find_element_by_id with find_element_by_name or find_element_by_tag_name based on your requirement

Answered By: Lalit Gehani
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


# wait until present
WebDriverWait(driver, waittime).until(
    EC.presence_of_element_located((By.CSS_SELECTOR, css_selector))
)

# wait until visible
WebDriverWait(driver, waittime).until(
    EC.visibility_of_element_located((By.CSS_SELECTOR, css_selector))
)
Answered By: lbsweek

I hope that’s might help:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec

driver = webdriver.Chrome()
driver.get(myURL)
wait = WebDriverWait(driver, 10) 

wait.until(ec.presence_of_element_located((By.XPATH, myXPATH)))

I recommend you to read this article to make it more clear.

Answered By: Dan H