WebDriver:检查元素是不是存在? [复制]
Posted
技术标签:
【中文标题】WebDriver:检查元素是不是存在? [复制]【英文标题】:WebDriver: check if an element exists? [duplicate]WebDriver:检查元素是否存在? [复制] 【发布时间】:2011-09-25 03:54:45 【问题描述】:如何通过 web 驱动检查元素是否存在?
使用 try catch 真的是唯一可行的方法吗?
boolean present;
try
driver.findElement(By.id("logoutLink"));
present = true;
catch (NoSuchElementException e)
present = false;
【问题讨论】:
@Michael Freidgeim:在你指责某人写了一个重复的问题之前,请检查问题的创建日期以确定哪个是重复的。 我不怪你。这只是一种整理方式——将相似的问题联系在一起。参见Should I vote to close a duplicate question, even though it's much newer, and has more up to date answers?“如果新问题是更好的问题或有更好的答案,那么投票关闭旧问题作为新问题的副本。” 【参考方案1】:你也可以这样做:
driver.findElements( By.id("...") ).size() != 0
这节省了讨厌的 try/catch
附言
或者更准确地说是@JanHrcek here
!driver.findElements(By.id("...")).isEmpty()
【讨论】:
或者更简洁:!driver.findElements(By.id("...")).isEmpty(); 如果元素存在,这些都可以正常工作,否则会花费太多时间 而且大小不是方法——driver.findElements( By.id("...") ).size != 0 这是在 selenium javadoc 中查找不存在元素的推荐方法,以防万一有人需要指向它的指针:selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/… 如果你碰巧像我一样,看着这个并说“什么......?那是调用相同的方法,因此也会抛出异常!?!”......看再次,它的复数形式 - 'findElements'。 ;)【参考方案2】:我同意 Mike 的回答,但如果没有找到可以打开/关闭的元素,则需要等待 3 秒,这在您经常执行此操作时很有用:
driver.manage().timeouts().implicitlyWait(0, TimeUnit.MILLISECONDS);
boolean exists = driver.findElements( By.id("...") ).size() != 0
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
如果您正在运行大量测试,将其放入实用程序方法中应该会提高性能
【讨论】:
因为隐式超时可以是3秒,也可以是其他值,所以应该先存储旧值,然后再重新设置。但不幸的是你可以设置值,但不能读取它——cool api 默认的隐式等待时间似乎是 0,(seleniumhq.org/docs/04_webdriver_advanced.html) 所以除非你把它配置得更长,否则这应该是没有必要的。 @Ralph 有没有办法获取当前值? 一开始你把它设置在某个地方,你应该自己存储它。也给出了默认值。【参考方案3】:正如评论所述,这是用 C# 而不是 Java,但想法是一样的。我已经广泛研究了这个问题,最终问题是,当元素不存在时,FindElement 总是返回异常。没有允许您获取 null 或其他任何内容的重载选项。这就是为什么我更喜欢这个解决方案而不是其他解决方案。
-
返回元素列表然后检查列表大小是否为 0 有效,但这样会失去功能。即使集合大小为 1,您也不能对链接集合执行 .click()。
您可以断言该元素存在,但通常会停止您的测试。在某些情况下,我有一个额外的链接可供点击,具体取决于我进入该页面的方式,如果它存在,我想点击它,否则继续前进。
只有不设置超时才会慢driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(0));
它实际上是一个非常简单和优雅的方法一旦创建。通过使用 FindElementSafe 而不是 FindElement,我不会“看到”丑陋的 try/catch 块,并且可以使用简单的 Exists 方法。看起来像这样:
IWebElement myLink = driver.FindElementSafe(By.Id("myId"));
if (myLink.Exists)
myLink.Click();
这是扩展 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;
IWebElement.Exists
/// <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 类实例,但从维护的角度来看这是一个坏主意。
【讨论】:
有两个问题:1) 错误的语言:Java 而不是 C#,2) 你使用了丑陋的 try/catch 解决方法(这就是问题所在,如果有比这种丑陋和缓慢的其他方法尝试/捕捉) 是的,那是 C#,但概念是一样的。 Try/Catch 只有在你必须经常这样做时才会变得丑陋。这就是为什么我将它封装在一个单独的方法中。最终的解决方案实际上非常漂亮。 bool 存在 = driver.FindElementSafe(by).Exists(); Try/Catch 不仅代码难看,运行时也很慢。用不同的方法封装它可以解决第一个问题,而不是第二个问题。 大声笑,UI 测试并不以速度着称,因此它是“敏捷测试金字塔”的顶端。与在 Chrome 或您正在使用的任何浏览器中获取和呈现页面所需的时间相比,在 try/catch id 中损失的一秒钟的时间相形见绌。如果你担心几分之一秒,那么你做错了测试类型。我建议在这种情况下考虑做更多的单元测试。【参考方案4】:这对我每次都有效:
if(!driver.findElements(By.xpath("//*[@id='submit']")).isEmpty())
//THEN CLICK ON THE SUBMIT BUTTON
else
//DO SOMETHING ELSE AS SUBMIT BUTTON IS NOT THERE
【讨论】:
【参考方案5】:我扩展了 Selenium WebDriver 的实现,在我的例子中是 HtmlUnitDriver 来公开一个方法
public boolean isElementPresent(By by)
像这样:
-
检查页面是否在超时时间内加载。
加载页面后,我将 WebDriver 的隐式等待时间降低到几毫秒,在我的情况下为 100 毫秒,可能也应该与 0 毫秒一起使用。
调用 findElements(By),WebDriver 即使找不到元素也只会等待上面的时间量。
将隐式等待时间缩短以等待未来的页面加载
这是我的代码:
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");
【讨论】:
【参考方案6】:使用 Java 编写以下方法:
protected boolean isElementPresent(By by)
try
driver.findElement(by);
return true;
catch(NoSuchElementException e)
return false;
在断言期间调用上述方法。
【讨论】:
我看不出这是如何回答这个问题的:“使用 try catch 真的是唯一可能的方法吗?”?【参考方案7】:你可以做一个断言。
看例子
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);
【讨论】:
这看起来很有趣,但你能澄清一下那是什么驱动程序吗?WebDriver
javadocs 不显示 asserts()
方法。【参考方案8】:
String link = driver.findElement(By.linkText(linkText)).getAttribute("href")
这将为您提供元素指向的链接。
【讨论】:
但是,如果带有文本“linkText”的元素不存在,这将导致 Nullpointer 异常——它最终与 nu1silva 发布的相同的无效想法【参考方案9】:使用 selenium-java.jar 的 2.21.0 版本,您可以做到这一点;
driver.findElement(By.id("...")).isDisplayed()
【讨论】:
你确定:我希望driver.findElement(By.id("..."))
抛出异常。
它确实仍然抛出异常 nin 2.21.0 OpenQA.Selenium.NoSuchElementException : Unable to locate element: "method":"id","selector":"FormButtonPanel_ButtonCancel" 命令持续时间或超时: 4 毫秒有关此错误的文档,请访问:seleniumhq.org/exceptions/no_such_element.html 构建信息:版本:'2.21.0',修订:'16552',时间:'2012-04-11 19:08:38' 系统信息:os .name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.6.0_22' 驱动信息: driver.version: EventFiringWebDriver
-1 这是错误的。 isDisplayed 可用于测试元素是否现在可见,而不是它是否存在于 dom 中。
-1 这与页面上是否存在元素不是一回事。【参考方案10】:
据我了解,这是使用网络驱动程序的默认方式。
【讨论】:
以上是关于WebDriver:检查元素是不是存在? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
Selenium Webdriver:如何检查特定屏幕上是不是存在 ui 元素,无论它当前是不是可见/可点击