混合使用隐式和显式等待

4

文档中写道:

隐式等待是告诉WebDriver在尝试查找元素或多个元素时,如果它们不立即可用,要轮询DOM一定的时间。

子问题:

在使用find_elements_by_(复数)的情况下,implicit_wait会等待多少个元素存在后才继续执行脚本?或者implicit_wait只适用于find_element_by_(单数)?如果是这样,那么文档中的“或元素”是什么意思?

一个SO答案中我读到最好不要在同一个脚本中同时使用隐式和显式等待,我注意到这一点,因为我希望测试尽可能健壮。

既然我知道肯定会用到 WebDriverWait,那么这是否意味着我需要在我的 unittestsetUp 方法中摆脱 implicit_wait,并且每次使用任何 find_element_by_ 方法时都要使用 WebDriverWait

(我宁愿不这样做;虽然我可以将每个 find_element_by_ 方法放在自己的自定义函数中 - 每个都包装在自己的 WebDriverWait 中 - 但感觉不应该这样做)。

所以我的主要问题是:

我能否保留我的测试 setUp 方法中的 implicit_wait,然后只在我知道需要它的 find_elements_by_ 和其他地方使用 WebDriverWait


1
我不会混合使用两种方法。每次我都会使用WebDriverWait。Selenium不知道在元素可用之前你需要等待多久,这就是为什么有这个选项的原因。此外,隐式等待将一直等到找到该元素。找到元素并不等于元素可用。 - Arran
+1 我不知道有这个区别。我开始怀疑为什么 implicitly_wait 在 API 中存在!你如何检查元素是否可用?我看到了 expected_conditions.element_to_be_clickable,但不确定还能用什么其他方式。 - KnewB
可能是selenium webdriver - 显式等待 vs 隐式等待的重复问题。 - Lesmana
1个回答

2
“既然我知道有时候我肯定需要 WebDriverWait,这是否意味着我需要在我的单元测试 setUp 方法中摆脱 implicit_wait,并且在每次使用任何 find_element_by_ 方法时都使用 WebDriverWait?”
是的。正如您在链接到的问题中看到的那样,如果同时使用两种类型的等待,您将遇到不希望出现的行为。这不仅是理论上的。我亲身经历了这种行为,试图调试它,找到了您链接到的问题,然后从我的测试套件中删除了所有隐式等待。
我开发了一个来帮助设置显式等待(并执行大量其他操作)。假设您已经拥有一个具有 Selenium Web Driver 的 driver 对象:
from selenium.webdriver.common.by import By
import selenic.util

util = selenic.util.Util(driver)

# This goes through util and uses the explicit wait set by util.
foo = util.find_element((By.CSS_SELECTOR, "..."))

# For special cases that take longer to give results.
with util.local_timeout(10):
    # The timeout is set to 10 for calls in this with block.
    bar = util.find_element(...)
# The timeout is restored to what it was just before the with.

有时候你根本不需要使用等待,因为在逻辑上如果元素A存在,则元素B也存在,所以你不必等待它。例如,如果你想要一个已经从Selenium获取的元素的父元素,可以使用parent = foo.find_element_by_xpath("..")
至于find_elements的行为,它会在确定有结果返回时立即返回。这可能意味着在find_elements找到要返回的内容后,如果稍后出现其他元素,它只会得到一个元素。

关于您提到从Selenium获取元素的父级,这是否意味着所有浏览器在元素本身之前始终使其父级DOM准备就绪并可见? - KnewB
1
我在谈论纯粹的存在。如果元素X存在于DOM树中,并且它不是树的根,则X的父级必须存在于树中。我也希望这对可见性也成立,但我不确定它是否在所有情况下都成立。然而,如果您开始查看像可点击性这样的东西,那么最好使用显式等待。其中一些也与正在测试的软件的逻辑有关。如果应用程序通过一次将其插入DOM树来创建<ul>元素,则当我找到其中的第一个<li>时,我知道其他<li>元素也存在。 - Louis
非常感谢。希望您不介意再问一个问题。关于find_elements,它会在确定有结果返回时立即返回;例如,如果页面仍在加载或AJAX正在加载某些内容,那么如何使find_elements返回最大/最终匹配元素的数量?您是否总是需要使用WebDriverWait .until find_elements == known_expected_num_of_elements?或者,通常如何使用find_elements,考虑到大多数Web应用程序都非常动态? - KnewB
1
是的,你必须寻找一个指示AJAX操作完成的标志。这个标志可能取决于你的应用程序。就像你所建议的那样,它可以是检查若干元素,或者检查你知道是AJAX操作输出的最后一个元素的存在性。(比如在动态分页数据表格的结尾处的页脚)。有时这意味着你要在考虑可测试性的前提下设计你的应用程序。 - Louis
我从文档中看到WebDriver可能在页面加载完成之前就返回控制权,所以我也会应用你的建议。 - KnewB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接