Breedly
Breedly

Reputation: 14226

Selenium waitForElement

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.

Upvotes: 48

Views: 102187

Answers (14)

Hanegbusa
Hanegbusa

Reputation: 23

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.

Upvotes: 0

andrewchan2022
andrewchan2022

Reputation: 5300

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))
)

Upvotes: 0

Lalit Gehani
Lalit Gehani

Reputation: 71

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

Upvotes: 0

John LeComte
John LeComte

Reputation: 21

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

Upvotes: 1

Diego Orellana
Diego Orellana

Reputation: 1024

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)

Upvotes: 0

Ben
Ben

Reputation: 317

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)

Upvotes: 1

Dave Koo
Dave Koo

Reputation: 463

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')

Upvotes: 21

onder.diri
onder.diri

Reputation: 26

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..

Upvotes: 0

TheDawg
TheDawg

Reputation: 23

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

Upvotes: 2

unutbu
unutbu

Reputation: 879561

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)

Upvotes: 58

Deven Kalra
Deven Kalra

Reputation: 31

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.

Upvotes: 3

jcfollower
jcfollower

Reputation: 3158

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")

Upvotes: 1

jro
jro

Reputation: 9474

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.

Upvotes: 1

naeg
naeg

Reputation: 4002

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.

Upvotes: 7

Related Questions