硒:检查元素的存在
Posted
技术标签:
【中文标题】硒:检查元素的存在【英文标题】:Selenium: Check for the presence of element 【发布时间】:2018-11-09 15:43:48 【问题描述】:在实时自动化中,我们是否在对其执行某些操作之前检查每个元素(在测试中)是否存在?
只要有findElement
语句,就有可能出现NoSuchElementException。我的问题是我们是否每次都检查元素的存在?
是否每个findElement
语句都需要被try-catch
块包围?
【问题讨论】:
【参考方案1】:有两种情况需要考虑:
-
元素是否存在;表示它是否存在于 DOM 中。
元素是否可见;意味着它在 DOM 中并且没有 hidden 或等效标志。
对于第一种情况,我使用以下辅助方法:
this.waitForElement = function(locator)
browser.wait(function()
return browser.isElementPresent(locator);
, testData.Timeout.TWO_MINUTES);
;
这将等待与提供的定位器匹配的元素出现的任意时间(它存在于 DOM 中)。
对于第二种情况,我使用这个辅助方法:
this.waitForElementIsVisible = function(el)
let EC = protractor.ExpectedConditions;
browser.wait(EC.visibilityOf(el), testData.Timeout.TWO_MINUTES, "Element did not become visible after 2 minutes");
;
这将WebElement
作为单个参数并等待直到元素变为可见(它存在于DOM中并且不会通过css样式或其他方式隐藏)
另外,我还发现这个辅助方法对于测试表单中的错误状态很有用:
this.waitForElementIsClickable = function(el)
let EC = protractor.ExpectedConditions;
browser.wait(EC.elementToBeClickable(el), testData.Timeout.TWO_MINUTES, "Element did not become clickable after 2 minutes");
;
将WebElement
作为第一个参数并等待直到可以单击该WebElement。
注意,我正在使用量角器,并在这些 sn-ps 中引用量角器。因此,除非您也使用量角器,否则这些可能无法通过直接复制+粘贴来 100% 工作。不过应该很容易调整它们以适应您的设置。
【讨论】:
【参考方案2】:您可能会发现使用AbstractWebDriverEventListener 类特别有用。该类实现了接口WebDriverEventListener,它为WebDriver触发的事件定义了before
和after
钩子。
可以实现一个这样的前钩子beforeFindBy 来检查元素的存在。例如:
public void beforeFindBy(By by, WebElement element, WebDriver driver)
// Explicit wait to check for the presence of the element using the "by" locator
类似地,可以实现 before 钩子 beforeClickOn 以在对该元素执行点击事件之前检查该元素是否可点击。
【讨论】:
谢谢。我发现这很有用。 当试图实现这个时,得到类型不匹配错误为***.com/questions/50620820/… 考虑一下,我在beforeFindBy
方法中使用try-catch
块来捕获异常(例如:NoSuchElementException
)。您能否为我提供一个解决方案,以在出现异常时停止该特定测试并继续下一个测试。
这与使用隐式等待有什么不同吗?【参考方案3】:
检查网页元素是否存在的最直接、最简单的方法是使用返回数组的 findElements()(注意复数形式),即
if (driver.findElements(By.xpath("//a")).isEmpty())
// no links exist
同样的方法可以用来检查单个元素,它不必是一个数组。返回的 .size() 为零表示没有匹配项,因此所需的元素不在 DOM 中。
有些人认为,更好的方法是将 .findElement 包装在一个方法中,该方法确实会尝试/捕获并记录/响应各种结果,例如未找到元素或陈旧元素等。
我在测试中使用这两种方法,并使用我自己的存在函数和 .findElements 逻辑,但将包装器用于其他场景。
【讨论】:
谢谢。我知道我们可以编写自己的函数以您提到的任何方式检查元素的存在。我的问题是我们是否在有findElement
语句的每个步骤中检查元素的存在?
这就是为什么我通常使用包装器,或者在我的特定情况下,使用页面对象模型。测试代码本身不应该一遍又一遍地重复相同的代码,但它确实需要足够健壮以能够处理预期元素不存在的情况,所以使用包装器或更好,使用页面对象型号/模式。【参考方案4】:
简短的回答:没有。 更长的答案:一种方法是等到“页面完成”指示器使用显式等待。这将表明您可以根据需要安全地找到元素。如果其中一个元素不可用,则测试将失败,表明它找不到该元素。 在测试中根据需要使用显式等待(当您期望页面/DOM 发生更改时)。
但同样,对这个问题及其答案也有一些看法。在整个过程中检查/等待元素是否存在确实需要花费运行时间,并且可能只会延长可能更快失败的测试。
【讨论】:
【参考方案5】:一一回答你的问题:
“在实时自动化中,我们是否在对每个元素执行某些操作之前检查每个元素(在测试中)是否存在”:是,只要用户是重定向到新页面,您需要确保元素的 state 符合您所需的操作。有 3 个最广泛使用的 ExpectedConditions 可以与 WebDriverWait 结合使用来验证元素的状态,如下所示:
presenceOfElementLocated
presenceOfElementLocated(By locator) 定义如下:
public static ExpectedCondition<WebElement> presenceOfElementLocated(By locator)
Description : An expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible.
visibilityOfElementLocated
visibilityOfElementLocated(By locator) 定义如下:
public static ExpectedCondition<WebElement> visibilityOfElementLocated(By locator)
Description : An expectation for checking that an element is present on the DOM of a page and visible. Visibility means that the element is not only displayed but also has a height and width that is greater than 0.
elementToBeClickable
elementToBeClickable(By locator) 定义如下:
public static ExpectedCondition<WebElement> elementToBeClickable(By locator)
Description : An expectation for checking an element is visible and enabled such that you can click it.
“只要有 findElement 语句,就有可能出现 NoSuchElementException”:没有,完全没有。如果你构造一个正确的Locator Strategy,你就不会面对
NoSuchElementException
。
这里有关于NoSuchElementExeption, selenium unable to locate element的详细讨论
Does every findElement statement need to be surrounded by try-catch block
:不,并非总是如此。如果您的用例涉及处理肯定和否定两种情况,那么try-catch
块是完美的。
【讨论】:
感谢您的详细解释。我会在WebDriverEventListener
接口中使用ExpectedConditions
和WebDriverWait
以上是关于硒:检查元素的存在的主要内容,如果未能解决你的问题,请参考以下文章