如何让Selenium Web Driver等待元素可访问,而不仅仅是存在?

时间:2012-02-06 14:38:20

标签: python selenium webdriver

我正在为Web应用程序编写测试。某些命令会拉出对话框,这些对话框具有可见的控件,但暂时不可用。 (它们是灰色的,但是webdriver仍然看到它们可见)。

如何告诉Selenium等待元素实际可访问,而不仅仅是可见?

    try:
        print "about to look for element"
        element = WebDriverWait(driver, 10).until(lambda driver : driver.find_element_by_id("createFolderCreateBtn"))
        print "still looking?"
    finally: print 'yowp'

以下是我尝试过的代码,但它在可用之前“看到”按钮,并且基本上是在假定的“等待”之后收费。

请注意,我可以在代码中填充十秒钟而不是这样,代码将正常工作,但这是丑陋,不可靠和低效的。但它确实证明问题只是“点击”命令在控制的可用性之前飙升。

4 个答案:

答案 0 :(得分:16)

我认为事件时间表是这样的:

  1. 页面上没有必要的元素。
  2. 显示所需元素,但已禁用:
    <input type="button" id="createFolderCreateBtn" disabled="disabled" />
  3. 需要的元素变为启用:
    <input type="button" id="createFolderCreateBtn" />
  4. 目前,您正在按ID搜索元素,并在步骤2中找到一个,这比您需要的更早。你需要做的是通过xpath搜索它:

    //input[@id="createFolderCreateBtn" and not(@disabled)]
    

    区别在于:

    from lxml import etree
    
    
    html = """
    <input type="button" id="createFolderCreateBtn" disabled="disabled" />
    <input type="button" id="createFolderCreateBtn" />
    """
    
    tree = etree.fromstring(html, parser=etree.HTMLParser())
    
    tree.xpath('//input[@id="createFolderCreateBtn"]')
    # returns both elements:
    # [<Element input at 102a73680>, <Element input at 102a73578>]
    
    
    tree.xpath('//input[@id="createFolderCreateBtn" and not(@disabled)]')
    # returns single element:
    # [<Element input at 102a73578>]
    

    总结一下,这是你的固定代码:

    try:
        print "about to look for element"
        element_xpath = '//input[@id="createFolderCreateBtn" and not(@disabled)]'
        element = WebDriverWait(driver, 10).until(
                lambda driver : driver.find_element_by_xpath(element_xpath)
        )
        print "still looking?"
    finally: 
        print 'yowp'
    

    更新:
    用实际的webdriver重复它。
    这是example.html页面代码:

    <input type="button" id="createFolderCreateBtn" disabled="disabled" />
    <input type="button" id="createFolderCreateBtn" />
    

    这是ipython会话:

    In [1]: from selenium.webdriver import Firefox
    
    In [2]: browser = Firefox()
    
    In [3]: browser.get('file:///tmp/example.html')
    
    In [4]: browser.find_elements_by_xpath('//input[@id="createFolderCreateBtn"]')
    Out[4]: 
    [<selenium.webdriver.remote.webelement.WebElement at 0x103f75110>,
     <selenium.webdriver.remote.webelement.WebElement at 0x103f75150>]
    
    In [5]: browser.find_elements_by_xpath('//input[@id="createFolderCreateBtn" and not(@disabled)]')
    Out[5]: 
    [<selenium.webdriver.remote.webelement.WebElement at 0x103f75290>]
    

    更新2:

    它也适用于此:

    <input type="button" id="createFolderCreateBtn" disabled />
    

答案 1 :(得分:12)

    print time.time()
    try:
        print "about to look for element"
        def find(driver):
            e = driver.find_element_by_id("createFolderCreateBtn")
            if (e.get_attribute("disabled")=='true'):
                return False
            return e
        element = WebDriverWait(driver, 10).until(find)
        print "still looking?"
    finally: print 'yowp'
    print "ok, left the loop"
    print time.time()

这是我们最终的结果。 (感谢lukeis和RossPatterson。)请注意,我们必须按ID找到所有项目,然后按“禁用”过滤。我更喜欢单一的搜索模式,但你能做什么?

答案 2 :(得分:0)

这里已经发布了一些很棒的答案,但我想我会添加我的解决方案。显式等待是用于测试硒的重要功能。然而,显式等待仅执行Thread.Sleep()的功能,您只能设置一次。以下功能是我过去几分钟“刮掉”的功能。它等待元素“可访问”。

    //ALTERNATIVE FOR THREAD.SLEEP
public static class Wait
{  
    //public static void wait(this IWebDriver driver, List<IWebElement> IWebElementLIst)
    public static void wait(this IWebDriver driver, By bylocator)
    {
        bool elementPresent = IsPresent.isPresent(driver, bylocator);
        while (elementPresent != true)
        {
            Thread.Sleep(1000);

            elementPresent = IsPresent.isPresent(driver, bylocator); 

        }

    }

}

它在C#中,但要适应它并不会那么困难。希望这可以帮助。

答案 3 :(得分:0)

我认为这些方面的内容也应该有效:

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

browser = webdriver.Firefox()
wait = WebDriverWait(browser, 30)
wait.until(expected_conditions.presence_of_element_located((By.XPATH, "//*[@id='createFolderCreateBrn' and not(@disabled)]")))