繁体   English   中英

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

[英]Test if an element is present using Selenium WebDriver

有没有办法测试元素是否存在? 任何findElement方法都会以异常结束,但这不是我想要的,因为元素可能不存在,这没关系。 那不是测试失败,所以异常不能成为解决方案。

我找到了这篇文章: Selenium C# WebDriver: Wait until element is present

但这是针对 C# 的,我不太擅长。 Java 中的代码是什么? 我在Eclipse中尝试过,但我没有把它正确地放入 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);
    }
}

使用findElements而不是findElement

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

要检查元素是否存在,你可以试试这个

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

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

官方文档推荐这种方法:

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

一个简单地查找元素并确定它是否存在的私有方法怎么样:

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);
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);
}

我遇到过同样的问题。 对我来说,根据用户的权限级别,某些链接、按钮和其他元素不会显示在页面上。 我的套件的一部分是测试应该丢失的元素是否丢失。 我花了几个小时试图弄清楚这一点。 我终于找到了完美的解决方案。

它的作用是告诉浏览器查找任何和所有基于指定的元素。 如果结果为0 ,则表示未找到基于规范的元素。 然后我让代码执行一个 if 语句,让我知道它没有找到。

这是在C# ,因此需要对Java进行翻译。 但应该不会太难。

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 whats in the else statement
if (deviceNotFound.Count > 0 && deviceNotFound[0].Displayed){
    //script to execute if element is found
} else {
    //Test script goes here.
}

我知道我对 OP 的回应有点晚了。 希望这对某人有所帮助!

试试这个:调用这个方法并传递 3 个参数:

  1. WebDriver 变量。 // 假设 driver_variable 作为驱动程序。
  2. 您要检查的元素。 应该提供 from By 方法。 // 例如:By.id("id")
  3. 以秒为单位的时间限制。

示例:waitForElementPresent(driver, 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
}

您可以通过在 try catch 语句之前缩短 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;
        }
    }

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

如果你在 ruby​​ 中使用 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

如果你的元素不存在,你的规范将通过,但如果元素存在,它会抛出一个错误,测试失败。

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

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

这是整洁的,可重复使用的,可维护的......所有这些好东西;-)

public boolean isElementDisplayed() {
        return !driver.findElements(By.xpath("...")).isEmpty();
    }

我在 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");

这对我有用..如果我错了,请建议我..

这应该这样做:

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"));
    });

Explicit 将在某些操作之前检查元素是否存在。 隐式等待可以在代码的每个地方调用。 例如在一些 AJAX 操作之后。

您可以在SeleniumHQ 页面找到更多信息

给我的代码片段。 因此,下面的方法检查页面上是否存在随机网络元素“创建新应用程序”按钮。 请注意,我使用的等待时间为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;
    }
}

我会使用类似的东西(使用 Scala [旧的“好”Java 8 中的代码可能与此类似]):

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))

在 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()) {
    ....
}

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

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();
}

场景 2:您想等待 WebElement 在 UI 中可见

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

场景 3:您的测试不稳定,因为 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);
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM