使用 Selenium WebDriver 测试元素是否存在

有没有一种方法来测试一个元素是否存在?任何 FindElement方法都会以异常结束,但这不是我想要的,因为可能有一个元素不存在,这没问题。这不是测试失败,因此异常不能成为解决方案。

我发现了这个帖子: Selenium C # WebDriver: 等到元素出现

但这是针对 C # 的,我不是很擅长。Java 中的代码是什么?我在 日食中尝试了一下,但是我没有把它正确地放入 Java 代码中。

这是密码:

public static class WebDriverExtensions{
public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds){


if (timeoutInSeconds > 0){
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
return wait.Until(drv => drv.FindElement(by));
}


return driver.FindElement(by);
}
}
423531 次浏览
public static WebElement FindElement(WebDriver driver, By by, int timeoutInSeconds)
{
WebDriverWait wait = new WebDriverWait(driver, timeoutInSeconds);
wait.until( ExpectedConditions.presenceOfElementLocated(by) ); //throws a timeout exception if element not present after waiting <timeoutInSeconds> seconds
return driver.findElement(by);
}

使用 findElements代替 findElement

如果没有找到匹配的元素而不是异常,findElements将返回一个空列表。

要检查元素是否存在,可以尝试这样做

Boolean isPresent = driver.findElements(By.yourLocator).size() > 0

如果至少找到一个元素,则返回 true; 如果不存在,则返回 false。

官方文件推荐这种方法:

不应该使用 findElement 查找不存在的元素,而应该使用 findElements (By)并断言零长度响应。

我也有同样的问题。对我来说,根据用户的权限级别,一些链接、按钮和其他元素不会显示在页面上。我的套件的一部分是测试 应该缺失的元素,缺失的元素。我花了好几个小时才想明白。我终于找到了完美的解决方案。

它告诉浏览器基于指定的。如果它的结果是 0,那就意味着没有找到基于规范的元素。然后我让代码执行一个 * if 语句来告诉我没有找到它。

这是在 C # ,所以翻译将需要做到 爪哇咖啡。但它不应该太难。

public void verifyPermission(string link)
{
IList<IWebElement> adminPermissions = driver.FindElements(By.CssSelector(link));
if (adminPermissions.Count == 0)
{
Console.WriteLine("User's permission properly hidden");
}
}

根据您的测试需要,还可以选择另一条路径。

下面的代码片段检查页面上是否存在非常特定的元素。根据元素的存在,我让测试执行一个 if else。

如果元素存在并显示在页面上,我有 console.write让我知道并继续。如果有问题的元素存在,我就不能执行我需要的测试,这是需要设置这个测试的主要原因。

如果元素 没有存在并且没有显示在页面上,那么在 If else 执行测试中就有 else。

IList<IWebElement> deviceNotFound = driver.FindElements(By.CssSelector("CSS LINK GOES HERE"));
// If the element specified above results in more than 0 elements and is displayed on page execute the following, otherwise execute what’s in the else statement
if (deviceNotFound.Count > 0 && deviceNotFound[0].Displayed){
// Script to execute if element is found
} else {
// Test script goes here.
}

我知道我对观察所的反应有点晚了,希望这能帮到别人!

使用一个私有方法,只需查找元素并确定它是否像下面这样存在:

private boolean existsElement(String id) {
try {
driver.findElement(By.id(id));
} catch (NoSuchElementException e) {
return false;
}
return true;
}

这将是相当容易,并做的工作。

您甚至可以更进一步,使用 By elementLocator作为参数,如果您希望通过除 id 之外的其他方式查找元素,则可以消除问题。

我发现这对 Java 很有用:

WebDriverWait waiter = new WebDriverWait(driver, 5000);
waiter.until( ExpectedConditions.presenceOfElementLocated(by) );
driver.FindElement(by);

我在 Java 中发现的最简单的方法是:

List<WebElement> linkSearch=  driver.findElements(By.id("linkTag"));
int checkLink = linkSearch.size();


if(checkLink!=0) {
// Do something you want
}

要查找某个元素是否存在,我们必须使用 findElements ()方法而不是 findElement () ..。

int i = driver.findElements(By.xpath(".......")).size();
if(i=0)
System.out.println("Element is not present");
else
System.out.println("Element is present");

这招对我很管用。

如果您在 露比中使用的是 rspec-WebDriver,那么您可以使用这个脚本,假设一个元素实际上不应该存在,并且它是一个通过的测试。

首先,从类 RB 文件中编写这个方法:

class Test
def element_present?
begin
browser.find_element(:name, "this_element_id".displayed?
rescue Selenium::WebDriver::Error::NoSuchElementError
puts "this element should not be present"
end
end

然后,在规范文件中调用该方法。

before(:all) do
@Test= Test.new(@browser)
end


@Test.element_present?.should == nil

如果您的元素是 没有,您的规范将通过,但如果元素是存在的,它将抛出一个错误,测试失败。

这个应该可以:

try {
driver.findElement(By.id(id));
} catch (NoSuchElementException e) {
//do what you need here if you were expecting
//the element wouldn't exist
}

你可以尝试隐式等待:

WebDriver driver = new FirefoxDriver();
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
driver.Url = "http://somedomain/url_that_delays_loading";
IWebElement myDynamicElement = driver.FindElement(By.Id("someDynamicElement"));

或者你可以尝试显式等待一:

IWebDriver driver = new FirefoxDriver();
driver.Url = "http://somedomain/url_that_delays_loading";
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.Id("someDynamicElement"));
});

在执行某些操作之前,将检查元素是否存在。可以在代码中的每个位置调用隐式等待。例如,在一些 阿贾克斯动作之后。

你可以在 SeleniumHQ 页面找到更多。

就我个人而言,我总是混合使用上面的答案,创建一个可重用的静态实用方法,使用 size() > 0的建议:

public Class Utility {
...
public static boolean isElementExist(WebDriver driver, By by) {
return driver.findElements(by).size() > 0;
...
}

这是整洁的、可重用的、可维护的等等ーー所有这些好东西; -)

试试这个:

调用此方法并传递三个参数:

  1. WebDriver 变量。假设 Driver _ variable 驱动程序变量作为驱动程序。
  2. 要检查的元素。它应该提供一个 方法。例子: By.id (“ id”)
  3. 以秒为单位的时间限制。

示例: whitForElementCurrent (驱动程序,By.id (“ id”) ,10) ;

public static WebElement waitForElementPresent(WebDriver driver, final By by, int timeOutInSeconds) {


WebElement element;


try{
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); // Nullify implicitlyWait()


WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
element = wait.until(ExpectedConditions.presenceOfElementLocated(by));


driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); // Reset implicitlyWait
return element; // Return the element


} catch (Exception e) {
e.printStackTrace();
}
return null;
}

这对我有用:

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

我正在给出我的代码片段。因此,下面的方法检查网页上是否存在随机的网页元素“ 创建新应用程序”按钮。注意,我将等待时间用作 0秒。

public boolean isCreateNewApplicationButtonVisible(){
WebDriverWait zeroWait = new WebDriverWait(driver, 0);
ExpectedCondition<WebElement> c = ExpectedConditions.presenceOfElementLocated(By.xpath("//input[@value='Create New Application']"));
try {
zeroWait.until(c);
logger.debug("Create New Application button is visible");
return true;
} catch (TimeoutException e) {
logger.debug("Create New Application button is not visible");
return false;
}
}

通过在 试着接住语句之前缩短 Selenium 超时时间,可以使代码运行得更快。

我使用以下代码检查是否存在元素。

protected boolean isElementPresent(By selector) {
selenium.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
logger.debug("Is element present"+selector);
boolean returnVal = true;
try{
selenium.findElement(selector);
} catch (NoSuchElementException e) {
returnVal = false;
} finally {
selenium.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
}
return returnVal;
}

使用 Java 编写以下函数/方法:

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

在断言期间使用适当的参数调用该方法。

我会使用类似的代码(对于 Scala [旧的“好的”Java8中的代码可能与此类似]) :

object SeleniumFacade {


def getElement(bySelector: By, maybeParent: Option[WebElement] = None, withIndex: Int = 0)(implicit driver: RemoteWebDriver): Option[WebElement] = {
val elements = maybeParent match {
case Some(parent) => parent.findElements(bySelector).asScala
case None => driver.findElements(bySelector).asScala
}
if (elements.nonEmpty) {
Try { Some(elements(withIndex)) } getOrElse None
} else None
}
...
}

那么,

val maybeHeaderLink = SeleniumFacade getElement(By.xpath(".//a"), Some(someParentElement))
public boolean isElementDisplayed() {
return !driver.findElements(By.xpath("...")).isEmpty();
}

在2022年,现在可以在没有烦人的延迟或影响当前隐式等待值的情况下完成这项工作。

首先将您的 Selenium 驱动程序调到最新版本(目前为 4.1.2)。

然后您可以使用 getImplicitWaitTimeout,然后设置为0的超时,以避免等待,然后恢复您以前的隐式等待值,无论它是:

Duration implicitWait = driver.manage().timeouts().getImplicitWaitTimeout();
driver.manage().timeouts().implicitlyWait(Duration.ofMillis(0));
final List<WebElement> signOut = driver.findElements(By.linkText("Sign Out"));
driver.manage().timeouts().implicitlyWait(implicitWait); // Restore implicit wait to previous value


if (!signOut.isEmpty()) {
....
}

使用 IsDisplay ()方法尝试下面的代码来验证元素是否存在:

WebElement element = driver.findElements(By.xpath(""));
element.isDispplayed();

可能有多种原因导致您在使用 Selenium 驱动程序定位 WebElement 时观察到异常。

我建议你在不同的情况下应用以下建议:

场景1: 你只是想知道某个 WebElement 是出现在屏幕上还是 没有上。例如,保存按钮图标只会出现,直到表单被完全填充,您可能想检查 保存按钮是否出现在您的测试中。

使用以下代码-

public Boolean isElementLoaded(By locator){
return !getWebElements(this.driver.findElements(locator), locator).isEmpty();
}

在用户界面中显示 WebElement 之前,您需要等待

public List<WebElement> waitForElementsToAppear(By locator) {
return wait.until(visibilityOfAllElementsLocatedBy(by));
}

你的测试是片状的,因为 WebElement 有时会变得陈旧,并且与 DOM 分离。

protected final List<Class<? extends WebDriverException>> exceptionList =
List.of(NoSuchWindowException.class,
NoSuchFrameException.class,
NoAlertPresentException.class,
InvalidSelectorException.class,
ElementNotVisibleException.class,
ElementNotSelectableException.class,
TimeoutException.class,
NoSuchSessionException.class,
StaleElementReferenceException.class);


public WebElement reactivateWebElement(By by, WebElement element){
try {
wait.ignoreAll(exceptionList)
.until(refreshed(visibilityOf(element)));
logger.info(("Element is available.").concat(BLANK).concat(element.toString()));
} catch (WebDriverException exception) {
logger.warn(exception.getMessage());
} return this.driver.findElement(by);
}