【问题标题】:How to test for absence of an element without waiting for a 30 second timeout如何在不等待 30 秒超时的情况下测试元素是否缺失
【发布时间】:2014-06-23 13:10:30
【问题描述】:

我正在写一些功能测试,做一些简单的单页测试需要5分钟,因为find_element函数在找不到元素时需要30秒才能完成。我需要测试是否存在元素而不必等待超时。我一直在寻找,但到目前为止还没有找到 find_element() 的任何替代方法。这是我的代码:

def is_extjs_checkbox_selected_by_id(self, id):
    start_time = time.time()
    find_result =  self.is_element_present(By.XPATH, "//*[@id='" + id + "'][contains(@class,'x-form-cb-checked')]")  # This line is S-L-O-W
    self.step(">>>>>> This took " + str( (time.time() - start_time) ) + " seconds")
    return find_result

def is_element_present(self, how, what):
    try: self.driver.find_element(by=how, value=what)
    except NoSuchElementException, e: return False
    return True

谢谢。

嗯,我遵循了这里和其他链接中的大部分建议,最终未能实现目标。当找不到元素时,它具有完全相同的行为,需要 30 秒:

# Fail
def is_element_present_timeout(self, id_type, id_locator, secs_wait_before_testing):
    start_time = time.time()
    driver = self.driver
    time.sleep(secs_wait_before_testing)
    element_found = True
    try:
        element = WebDriverWait(driver, 0).until(
            EC.presence_of_element_located((id_type, id_locator))
        )
    except:
        element_found = False
    elapsed_time = time.time() - start_time
    self.step("elapsed time : " + str(elapsed_time))
    return element_found

这是使用获取所有元素的想法的第二种方法

# Fail
def is_element_present_now(self, id_type, id_locator):
    driver = self.driver
    # This line blocks for 30 seconds if the id_locator is not found, i.e. fail
    els = driver.find_elements(By.ID, id_locator)
    the_length = els.__len__()
    if the_length == 0:
        result = False
    else:
        result = True
    self.step('length='+str(the_length))
    return result

注意,我不接受之前的回答,因为遵循海报的建议并没有产生成功的结果。

【问题讨论】:

标签: python selenium webdriver


【解决方案1】:

鉴于您在问题中显示的代码,如果您在 Selenium 确定元素丢失之前等待 30 秒,这意味着您正在使用隐式等待。您应该停止使用隐式等待并专门使用显式等待。原因是迟早您会想要使用显式等待来精确控制 Selenium 等待的时间。不幸的是,隐式等待和显式等待不能混为一谈。详情请见this answer

根据条件,我使用两种通用方法来测试元素是否缺失。在使用 Selenium 测试动态应用程序时,我们面临的一个问题如下: 此时您可以确定要检查其缺失的元素不会比检查的时间点? 例如,如果您执行一个单击按钮的测试,该按钮会启动一个 Ajax 请求,这可能会导致在请求失败时将指示错误的元素添加到 DOM,并且您在要求 Selenium 单击按钮后立即检查错误元素的存在,如果碰巧请求失败,您可能会错过错误消息。您必须至少稍等片刻才能让 Ajax 请求有机会完成。多长时间取决于您的应用程序。

话虽如此,这是我使用的两种方法。

将缺席与在场配对

我将缺席测试与在场测试配对,使用find_elements 而不是find_element,检查find_elements 返回的数组的长度是否为零。

“我将缺席测试与存在测试配对”是指我确定了一个条件,例如页面上另一个元素的 存在。这个条件必须是这样的,如果条件为真,那么我不需要等待来测试是否缺席:我知道如果条件为真,我想测试其缺席的元素必须最终不存在或出现在页面上。它不会在几分之一秒后出现。

例如,我有一个按钮,单击该按钮时会通过 Ajax 调用执行检查,一旦 Ajax 调用完成,就会在页面<p>Check complete</p> 上放置,如果有错误,则在其下方添加带有错误消息的段落。为了测试没有错误的情况,我会等待<p>Check complete</p> 出现,然后然后检查是否没有错误消息。我会使用find_elements 检查这些错误消息,如果返回列表的长度为0,我知道没有。检查这些错误消息本身不需要等待。

这也适用于不涉及 Ajax 的情况。 例如,如果服务器生成的页面有或没有某个元素,则无需等待,方法可以使用这里描述的。页面的“存在”(即页面已完成加载)是检查您要检查的元素是否不存在所需的唯一条件。

等待超时

如果我无法从某些积极条件中受益来配合我的缺勤检查,那么我会使用显式等待:

import selenium.webdriver.support.expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from nose.tools import assert_raises

def test():
    WebDriverWait(driver, timeout).until(
        EC.presence_of_element_located((By.CSS_SELECTOR, ".foo")))

assert_raises(TimeoutException, test)

driver 之前创建的Selenium 的WebDriver 上面的代码中,timeout 是所需的超时时间,assert_raises 只是可以使用的断言示例。如果引发TimeoutException,则断言通过。

【讨论】:

    【解决方案2】:

    在对此进行了研究但一无所获后,我终于想出了一个可以接受的解决方案。这是多么容易解决,这有点令人尴尬。我所要做的就是使用implicitly_wait() 函数来操作超时,由于某种原因我忽略了/没有注意到。我使用的是 Louis 提供的语法,但它会更简单,并且通过使用上面的原始 is_element_present() 函数并在 find_element() 函数之前和之后添加 driver.implicitly_wait() 函数来工作。

    # Success
    def is_element_present(self, id_type, id_locator):
        driver = self.driver
        element_found = True
        driver.implicitly_wait(1)
        try:
            element = WebDriverWait(driver, 0).until(
                EC.presence_of_element_located((id_type, id_locator))
            )
        except:
            element_found = False
        driver.implicitly_wait(30)
        return element_found
    

    【讨论】:

      【解决方案3】:

      我用Java写了一个简单的方法:

      public boolean isElementPresent(long waitTime, String elementLocation) {
          WebDriverWait wait = new WebDriverWait(driver, waitTime); // you can set the wait time in second
          try {
              wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(elementLocation)));
          } catch (Exception e) {
              return false;
          }
          return true;
      }
      

      (可以在python中查看示例:http://selenium-python.readthedocs.org/en/latest/waits.html

      【讨论】:

        猜你喜欢
        • 2017-02-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-11
        • 1970-01-01
        • 2015-07-09
        • 2019-01-03
        相关资源
        最近更新 更多