我正在使用selenium Web驱动程序和appium,因为这是移动应用程序自动化,

我正在尝试检查元素是否存在,并以此为条件。

 long starttime = System.currentTimeMillis();
 long endtime = starttime + 60*1000; // 60 seconds * 1000 ms/sec;


while(System.currentTimeMillis() < endtime)
{

    notcount = driver.findElement(By.id(AppConstants.notificationcount));

}

if(notcount.equals(null))

{

    System.out.println("No Element found");
}
else
{

    //SOME ANOTHER STEPS
}


这里的问题是元素不存在时,而是重定向到ELSE部分,硒停止执行并引发异常。

我不想使用List- findelements在这里,因为要花很长时间才能找到元素。

评论

我用谷歌搜索“硒等待,如果找不到,做点事”的头两个结果就解决了:)请参阅我的答案。

#1 楼

使用findElements代替findElement

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

要检查是否存在某个元素,可以尝试this

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


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

从以下位置复制文本:https ://stackoverflow.com/questions/7991522/selenium-webdriver-test-if-element-is-present

另一种可能性是使用Try / Catch构造,有关更多信息,请参见此:https ://stackoverflow.com/questions/6521270/webdriver-check-if-an-element-exists

评论


是的,我同意并且已经尝试了此解决方案,但是即使元素不存在也要花很长时间搜索,这就是为什么我提到我不想为此使用LIST或findelements的原因。

–伸出援助之手
2015年8月10日在2:59



请改用try / catch结构。但是,实际需要多长时间?除非您发现数百个元素,否则不会太多。我也想知道您是否真的想继续测试,如果找不到元素,那么为什么要寻找它呢?让测试失败。

– Niels van Reijmersdal
15年8月10日在6:40

我也很惊讶,我发现只有1个元素,并且只有webdriver需要花费很长时间。我希望测试继续进行,就像找不到元素,然后转到ELSE部分。

–伸出援助之手
15年8月10日在7:12

在测试中使用if / then / else构造对我来说是反模式。该测试应描述一个执行路径,并避免任何逻辑。如果某些东西阻塞了此执行路径,则按照建议快速失败。如果要涵盖多个执行路径,请创建多个测试,每个测试涵盖一个执行路径。

– dzieciou
15年8月19日在5:35



#2 楼

当您使用.findElement时,您遇到的是一种快速失败的行为。您实际上并不需要使用.findElements(el)来获得软故障行为。您可以执行以下操作:

protected void checkElementPresence(final WebDriver driver,final By by,final String errorMsg){
  new WebDriverWaitWithMessage(driver,10).failWith(errorMsg).until(new ExpectedCondition<Boolean>(){
    @Override public Boolean apply(    WebDriver webDriver){
      try {
        return driver.findElement(by).isDisplayed();
      }
 catch (      NoSuchElementException ignored) {
        return false;
      }
catch (      StaleElementReferenceException ignored) {
        return false;
      }
    }
  }
);


,但需要此支持类:

protected static class WebDriverWaitWithMessage extends WebDriverWait {

        private String message;

        public WebDriverWaitWithMessage(WebDriver driver, long timeOutInSeconds) {
            super(driver, timeOutInSeconds);
        }

        public WebDriverWait failWith(String message) {
            if (message == null || message.length() == 0) {
                throw new IllegalArgumentException("Error message must not be null nor empty");
            }
            this.message = message;
            return this;
        }

        @Override
        public <V> V until(Function<? super WebDriver, V> isTrue) {
            if (message == null) {
                return super.until(isTrue);
            } else {
                try {
                    return super.until(isTrue);
                } catch (TimeoutException e) {
                    throw new TimeoutException(message, e);
                }
            }
        }
    }


#3 楼

(请注意,我没有在Java中尝试过此操作,但这是在C#中的操作方法)。

您应该将findelement放在try / catch块中,以便如果找不到该元素,可以捕获异常并执行正确的操作。

看起来像这样:

try
{
    driver.FindElement(By.CssSelector("selector"));
} 
catch(NoSuchElementException)
{
    Console.WriteLine("Element does not exist!");
} 


编辑:
我会请注意,您似乎正在尝试实现自己的webdriver等待行为,因此请在此处查看第一个答案:https://stackoverflow.com/questions/11736027/webdriver-wait-for-element,其中说明了如何等待Java中具有显式等待的元素。

#4 楼

使用该代码行的异常处理块。
尝试
{
}
赶上
{
最后
{
}
如果找不到元素,然后执行finally块中的代码,并继续执行其他代码行

评论


请扩展您的答案,以说明它对现有答案(尤其是已接受的答案)的改进。

–凯特·保罗(Kate Paulk)
17年12月13日在12:18

#5 楼

public void sellProduct(){                          

            try {
                for(int i=0; i< 5 ;i++){
                    try {
                        if(!driver.findElements(By.xpath("/html/body/div[@class='container']/table[@class='table table-striped'][2]/tbody[@id='bought']/tr[@id="+i+"]/th[4]/button")).isEmpty())            {
                            try {
                                driver.findElement(By.xpath("/html/body/div[@class='container']/table[@class='table table-striped'][2]/tbody[@id='bought']/tr[@id="+i+"]/th[4]/button")).click();
                            } catch (NoSuchElementException e) {
                                e.printStackTrace();
                            }
                        }

                        else{
                            try {
                                System.out.println("no products to sell ");
                            } catch (NoSuchElementException e) {
                                e.printStackTrace();
                            }
                        }
                    } catch (NoSuchElementException e) {
                        e.printStackTrace();
                    }

                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


我编写了这段代码,但继续获取问题目标寡妇已关闭,我希望在找不到Web元素时退出循环。

评论


这个问题的公认答案对您有帮助吗?如果不是,请将此问题作为自己的问题发布,并解释为什么此处接受的答案无济于事。请不要发布“我有相同的问题”作为答案-您的帖子可能会被删除。

–凯特·保罗(Kate Paulk)
18年1月24日在16:53

#6 楼

我使用C#,但这是我使用的方法:

/// <summary>
    /// Looks to see if the passed in element is on the webpage or not. Returns true or false.
    /// </summary>
    /// <param name="by"></param>
    /// <param name="element"></param>
    /// <param name="driver"></param>
    /// <returns></returns>
    public static bool tryToFindElement(By by, out IWebElement element, IWebDriver driver)
    {
        try
        {
            element = driver.FindElement(by);
        }
        catch (NoSuchElementException)
        {
            element = null;
            return false;
        }
        return true;
    }

    /// <summary>
    /// Checks to see if the web element is displayed and enabled.
    /// </summary>
    /// <param name="element"></param>
    /// <returns></returns>
    public static bool isElementVisible(IWebElement element)
    {
        return element.Displayed && element.Enabled;
    }


我这样称呼它:

if (tryToFindElement(By.CssSelector("<CSS Selector>"), out element, driver))
                {
                    bool visible = isElementVisible(element);
                    if (visible == true)
                    {
                     //Do something
                    }
                }


#7 楼

我已经尝试过获得布尔响应的答案,但是正如我所看到的,只有当我们设置了驱动程序的超时时,这才可能实现。

我有20秒的超时时间,并且我遵循上述公认的答案。

因此,不仅要检查boolean isPresesnt = driver.findElements(by).size() > 0;,还是建议设置驱动程序的隐式超时。

driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);

希望有帮助!

#8 楼

只需将搜索元素的时间设置为隐式短时间
,这将导致列表返回为空
androidDriver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
List<AndroidElement> yesterdaysImage = androidDriver.findElementsById("MOBILE_PACKAGE_NAME:id/goals_item_yesterday");

(我知道这是Selenium,我发布了Appium,但是Appium是源自Selenium,因此此代码仍然有效)