如何使用 Selenium WebDriver 检查元素是否存在?

如何检查一个元素是否存在与网页驱动程序?

使用 try-catch 真的是唯一可行的方法吗?

boolean present;
try {
driver.findElement(By.id("logoutLink"));
present = true;
} catch (NoSuchElementException e) {
present = false;
}
495411 次浏览

据我所知,这是使用 web 驱动程序的默认方式。

你也可以这样做:

driver.findElements(By.id("...")).size() != 0

这样就省去了难堪的尝试/接球

附言:

或者更确切地说是@JanHrcek 给你

!driver.findElements(By.id("...")).isEmpty()

我同意 Mike 的回答的观点,但是如果没有找到可以打开/关闭的元素,那么会有一个隐式的3秒等待,如果你经常执行这个操作的话,这是很有用的:

driver.manage().timeouts().implicitlyWait(0, TimeUnit.MILLISECONDS);
boolean exists = driver.findElements( By.id("...") ).size() != 0
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);

如果要运行大量测试,将其放入实用程序方法中应该可以提高性能。

在2.21.0版的 selenium-java.jar 中,您可以做到这一点;

driver.findElement(By.id("...")).isDisplayed()
String link = driver.findElement(By.linkText(linkText)).getAttribute("href")

这将为您提供元素所指向的链接。

你可以做一个断言。

看看这个例子

driver.asserts().assertElementFound("Page was not loaded",
By.xpath("//div[@id='actionsContainer']"),Constants.LOOKUP_TIMEOUT);

你可以用这个,这是本地的:

public static void waitForElementToAppear(Driver driver, By selector, long timeOutInSeconds, String timeOutMessage) {
try {
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(selector));
}
catch (TimeoutException e) {
throw new IllegalStateException(timeOutMessage);
}
}

正如注释所说,这是在 C # 中,而不是在 Java 中,但是思想是一样的。我对这个问题进行了广泛的研究,最终的问题是,当元素不存在时,FindElement 总是返回一个异常。没有一个重载选项允许您获得 null 或任何其他值。这就是为什么我比较喜欢这个解决方案。

  1. 返回一个元素列表,然后检查列表大小是否为0可以工作,但是这样会失去功能。你不能。在链接集合上单击() ,即使集合大小为1。
  2. 您可以断言元素存在,但通常会停止测试。在某些情况下,我有一个额外的链接点击取决于我如何到达该网页,我想点击它,如果它存在或移动否则。
  3. 如果不设置超时 管理()。超时()。隐式等待(TimeSpan。 FromSecds (0)) ;,它只会慢下来
  4. 一旦方法被创建,它实际上是一个非常简单和优雅的方法。通过使用 FindElementSafe而不是 FindElement,我不会“看到”丑陋的 try/catch 块,我可以使用一个简单的 存在方法。看起来像这样:

    IWebElement myLink = driver.FindElementSafe(By.Id("myId"));
    if (myLink.Exists)
    {
    myLink.Click();
    }
    

Here is how you extend IWebElement & IWebDriver

IWebDriver.FindElementSafe

    /// <summary>
/// Same as FindElement only returns null when not found instead of an exception.
/// </summary>
/// <param name="driver">current browser instance</param>
/// <param name="by">The search string for finding element</param>
/// <returns>Returns element or null if not found</returns>
public static IWebElement FindElementSafe(this IWebDriver driver, By by)
{
try
{
return driver.FindElement(by);
}
catch (NoSuchElementException)
{
return null;
}
}

存在

    /// <summary>
/// Requires finding element by FindElementSafe(By).
/// Returns T/F depending on if element is defined or null.
/// </summary>
/// <param name="element">Current element</param>
/// <returns>Returns T/F depending on if element is defined or null.</returns>
public static bool Exists(this IWebElement element)
{
if (element == null)
{ return false; }
return true;
}

您可以使用多态性来修改 FindElement 的 IWebDriver 类实例,但是从维护的角度来看,这不是一个好主意。

我扩展了 Selenium WebDriver 实现,在我的例子中是 HtmlUnitDriver 来公开一个方法,

public boolean isElementPresent(By by){}

像这样:

  1. 检查页是否在超时期限内加载。
  2. 加载页面之后,我将 WebDriver 的隐式等待时间降低到一些毫秒,在我的示例中为100毫秒,但它可能也应该在0毫秒的情况下工作。
  3. 调用 findElements (By)。WebDriver 即使找不到元素,也只会等待从上面开始的时间。
  4. 提高将来页面加载的隐式等待时间

这是我的代码:

import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;


public class CustomHtmlUnitDriver extends HtmlUnitDriver {


public static final long DEFAULT_TIMEOUT_SECONDS = 30;
private long timeout = DEFAULT_TIMEOUT_SECONDS;


public long getTimeout() {
return timeout;
}


public void setTimeout(long timeout) {
this.timeout = timeout;
}


public boolean isElementPresent(By by) {
boolean isPresent = true;
waitForLoad();
// Search for elements and check if list is empty
if (this.findElements(by).isEmpty()) {
isPresent = false;
}
// Rise back implicitly wait time
this.manage().timeouts().implicitlyWait(timeout, TimeUnit.SECONDS);
return isPresent;
}


public void waitForLoad() {
ExpectedCondition<Boolean> pageLoadCondition = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver wd) {
// This will tel if page is loaded
return "complete".equals(((JavascriptExecutor) wd).executeScript("return document.readyState"));
}
};
WebDriverWait wait = new WebDriverWait(this, timeout);
// Wait for page complete
wait.until(pageLoadCondition);
// Lower implicitly wait time
this.manage().timeouts().implicitlyWait(100, TimeUnit.MILLISECONDS);
}
}

用法:

CustomHtmlUnitDriver wd = new CustomHtmlUnitDriver();
wd.get("http://example.org");
if (wd.isElementPresent(By.id("Accept"))) {
wd.findElement(By.id("Accept")).click();
}
else {
System.out.println("Accept button not found on page");
}

这对我每次都管用:

    if(!driver.findElements(By.xpath("//*[@id='submit']")).isEmpty()){
// Then click on the submit button
}else{
// Do something else as submit button is not there
}

使用 Java 编写以下方法:

protected boolean isElementPresent(By by){
try{
driver.findElement(by);
return true;
}
catch(NoSuchElementException e){
return false;
}
}

在断言期间调用上述方法。