使用webdriver查看元素是否存在而不抛出异常?

时间:2012-03-21 06:52:12

标签: java webdriver selenium-webdriver

我是Selenium webdriver的新手,也许这个问题很明显。我是这样的情况:

如果元素存在,请单击它并返回索引页面:

driver.findElement(By.id("...."])).click();

如果不退出,请跳过它并返回索引页面。测试仍在继续,没有任何异常抛出。

我知道一个解决方案:

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

所以我试过了:

if(driver.findElements(By.id("....")).size() > 0)
    {
        driver.findElement(By.id("....")).click();
        driver.findElement(By.cssSelector("...")).click();
    } 
else
    {
        driver.findElement(By.cssSelector("....")).click();
    }

但事实证明这很难看,因为如果我有10个要验证的元素,这个IF条件需要写10次。

任何变通方法都可以使它变得干净吗?

3 个答案:

答案 0 :(得分:1)

解决方案可能很多,但这可能会妨碍您的架构。

最简单的解决方案如下:

只需在某个实用程序类或某个地方创建一个类似optionalClick()的方法,其参数为:

  1. locator_keyword:{values:id或cssSelector或xpath etc}
  2. locator:{values:“q”}
  3. 方法步骤:

    1. 根据locator_keywordlocator
    2. 获取元素
    3. 检查元素是否存在并单击
    4. 否则不要做任何事
    5. 此方法可用作任何类型对象的通用类型。

答案 1 :(得分:1)

通过在循环内使用try-catch条件,有一些方法可以在不抛出异常的情况下查找元素。例如,我编写的这个方法(可以根据你使用的内容进行简化)将返回一个WebElement,它确保在返回给你之前它是可点击的:

public static WebElement getElementByLocator( By locator ) {
  driver.manage().timeouts().implicitlyWait( 5, TimeUnit.SECONDS );
  WebElement we = null;
  boolean unfound = true;
  int tries = 0;
  while ( unfound && tries < 10 ) {
    tries += 1;
    try {
      we = driver.findElement( locator );
      unfound = false; // FOUND IT
    } catch ( StaleElementReferenceException ser ) {                        
      unfound = true;
    } catch ( NoSuchElementException nse ) {                        
      unfound = true;
    } catch ( Exception e ) {
      staticlogger.info( e.getMessage() );
    }
  } 
  driver.manage().timeouts().implicitlyWait( DEFAULT_IMPLICIT_WAIT, 
      TimeUnit.SECONDS );
  return we;
}

答案 2 :(得分:0)

感谢使用findelements的指针。如果您不希望它过早返回,我认为您还需要等待逻辑。

这是我在c#中的解决方案。

它基本上重新实现了selenium库中的等待逻辑 - 不幸的是,等待的方法没有暴露(令人烦恼的是它也rethrows exceptions the wrong way并且丢失了堆栈跟踪!)。

你可能不得不为java修改一下 - 当你不能传递函数时,不确定selenium API是什么。

等待重新实现:

    private IWebElement WaitAndSeeIf(Func<IWebElement> canGet)
    {
        var end = DateTime.Now.AddSeconds(1);

        IWebElement element;
        while (true)
        {
            element = canGet();

            if (element != null)
                break;

            var time = DateTime.Now;
            if (time > end)
                break;

            Thread.Sleep(200);
        }
        return element;
    }

调用代码:

        var dashboardButton = WaitAndSeeIf(() =>
                                               {
                                                   var elements = Driver.FindElements(By.XPath("//button[contains(.//*,'Dashboard')]"));
                                                   return elements.Any() ? elements.Single() : null;
                                               });

到目前为止,我发现这在几个地方都很有用(检查extjs中是否存在对话框等),但是还是需要捣乱并使其可配置。我认为最好的办法是让它采取其他答案中提到的隐含等待时间。