WebDriver.findElements抛出InvalidElementStateException

时间:2012-09-11 13:09:44

标签: java selenium webdriver selenium-webdriver

我编写了一个简单的方法来检查是否启用了WebElement并将此方法放在我的测试用例Super Object中:

protected boolean isElementEnabled(By by) {
    // Temporarily set the implicit timeout to zero
    int originalTimeout = Integer.parseInt(System.getProperty(
            "com.brainshark.uitests.timeout", "120"));
    driver.manage().timeouts().implicitlyWait(0, TimeUnit.MILLISECONDS);
    // Check to see if there are any elements in the found list
    List<WebElement> elements = driver.findElements(by);
    boolean isEnabled = (elements.size() == 1)
            && elements.get(0).isEnabled();
    // Return to the original implicit timeout value
    driver.manage().timeouts()
            .implicitlyWait(originalTimeout, TimeUnit.SECONDS);
    return isEnabled;
}

我一直在使用它没有问题,但突然间我遇到了一个可重复的实例,此方法抛出InvalidElementStateException:

  

org.openqa.selenium.InvalidElementStateException:findElements   执行失败; SYNTAX_ERR:DOM异常12(警告:服务器   没有提供任何堆栈跟踪信息)命令持续时间或   超时:13毫秒构建信息:版本:'2.23.1',修订版:   '未知',时间:'2012-06-08 12:33:29'系统信息:os.name:'Windows   7',os.arch:'amd64',os.version:'6.1',java.version:'1.7.0_05'   驱动程序信息:driver.version:RemoteWebDriver会话ID:   ed1a9cbb238fa4dfb616ad81e7f60141

似乎失败取决于我正在搜索的定位器。这个定位器有什么固有的错误吗?

final By AdministrationButton = By
            .cssSelector("div#top-nav a[href~=CorpAdmin/DisplayInformation]");

要验证,上面的定位器正在尝试使用包含“CorpAdmin / DisplayInformation”的href属性来定位anchor元素,该属性是具有id = top-nav的div的后代。不应该像我使用的那个CSS定位器适用于ChromeDriver吗?有谁知道为什么像findElements这样的方法会抛出InvalidElementStateExceptions?提前谢谢!

附录:进一步调查显示,只有在我通过不同的方法从一个页面导航到另一个页面后,该方法才会失败。感觉某些东西变得陈旧或指的是不再存在的元素或者那种影响的东西。但是,我无法理解那是什么;相同的驱动程序对象可用于测试用例和页面对象,并且每次调用isElementEnabled时都会使用它。没有缓存或引用先前页面中的WebElements。我的驱动程序是否需要提醒您页面已更改?

附录2:情节变粗。现在我对之前的附录不太确定。导航到新页面后,事情仍然失败,但我不确定该定位器是否存在问题。我尝试用这样的调用来编写代码:

debug("Attempt 3...");
things = getDriver().findElements(By.cssSelector("div a"));
debug("Attempt 3 found " + things.size() + " things!");

这些调用成功,直到我离开我开始的页面。他们在与简单定位器匹配的页面上找到35个元素。但是,一旦我导航到新页面,我就会得到一个新的例外:

  

org.openqa.selenium.WebDriverException:findElements返回无效   值:“[{\”ELEMENT \“:\”:wdc:1347370086846 \“},{\”ELEMENT \“:   \“:wdc:1347370086847 \”},{\“ELEMENT \”:\“:wdc:1347370086848 \”},   {\“ELEMENT \”:\“:wdc:1347370086849 \”},{\“ELEMENT \”:   \“:wdc:1347370086850 \”},{\“ELEMENT \”:\“:wdc:1347370086851 \”},   {\“ELEMENT \”:\“:wdc:1347370086852 \”},{\“ELEMENT \”:   \“:wdc:1347370086853 \”},{\“ELEMENT \”:\“:wdc:1347370086854 \”},   {\“ELEMENT \”:\“:wdc:1347370086855 \”},{\“ELEMENT \”:   \“:wdc:1347370086856 \”},{\“ELEMENT \”:\“:wdc:1347370086857 \”},   {\“ELEMENT \”:\“:wdc:1347370086858 \”},{\“ELEMENT \”:   \“:wdc:1347370086859 \”},{\“ELEMENT \”:\“:wdc:1347370086860 \”},   {\“ELEMENT \”:\“:wdc:1347370086861 \”},{\“ELEMENT \”:   \“:wdc:1347370086862 \”},{\“ELEMENT \”:\“:wdc:1347370086863 \”},   {\“ELEMENT \”:\“:wdc:1347370086864 \”},{\“ELEMENT \”:   \“:wdc:1347370086865 \”},{\“ELEMENT \”:\“:wdc:1347370086866 \”},   {\“ELEMENT \”:\“:wdc:1347370086867 \”},{\“ELEMENT \”:   \“:wdc:1347370086868 \”},{\“ELEMENT \”:\“:wdc:1347370086869 \”}]“   (警告:服务器未提供任何堆栈跟踪信息)   命令持续时间或超时:9毫秒构建信息:版本:   '2.23.1',修订版:'未知',时间:'2012-06-08 12:33:29'系统   info:os.name:'Windows 7',os.arch:'amd64',os.version:'6.1',   java.version:'1.7.0_05'驱动程序信息:driver.version:RemoteWebDriver   会议ID:174adf3205213984172556afa718f6a1

Selenium是代表WebElements的吗?我想这些只是对象本身的引用。它们只有26个,而不是之前返回的35个(因为我们在不同的页面上,这可能是正确的数字)。不确定为什么某些东西是无效的或者是什么。如果我在上面的AdministrationButton的定位器上调用isElementEnabled,我会像以前一样得到InvalidElementSateException。

2 个答案:

答案 0 :(得分:2)

1)第一点。坦率地说,我不喜欢你的方法isElementEnabled是有组织的。 要了解selenium是否能够使用您的本地化元素进行操作,请尝试以下方法:

public boolean isElementPresent(By locatorKey) {
        try {
            driver.findElement(locatorKey);
            return true;
        } catch (org.openqa.selenium.NoSuchElementException e) {
            return false;
        }
    }

driver.findElement(By.cssSelector(....)).isEnabled();
driver.findElement(By.cssSelector(....)).isDisplayed()

但在使用这种方法之前,我建议你使用流利的等待。流畅的等待返回你通过定位器找到了web元素(注意:如果某些东西在流畅的情况下失败,那么你最好注意你的nepath元素的xpath或cssselector):

 public WebElement fluentWait(final By locator){
        Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
                .withTimeout(30, TimeUnit.SECONDS)
                .pollingEvery(5, TimeUnit.SECONDS)
                .ignoring(NoSuchElementException.class);

        WebElement foo = wait.until(
new Function<WebDriver, WebElement>() {
            public WebElement apply(WebDriver driver) {
                        return driver.findElement(locator);
                }
                }
);
                           return  foo;              }     ;

关于流利的等待我建议您阅读here

关于你找到cssSelector的方式坦率地说我也不喜欢它。 而不是"div#top-nav a[href~=CorpAdmin/DisplayInformation]" 试试这个 div[id='top'] nav a[href~='CorpAdmin/DisplayInformation'] 并始终使用css或xPAth检查您的本地化元素(例如在firepath中,firefox插件到firebug)。见下图: firepath localizing

希望这能以某种方式帮助你。

答案 1 :(得分:1)

顺便说一下,我遇到了类似的问题,例外。 Selenium webcrawling combo box 所以这种问题意味着你遇到了硒无法与之相互作用的元素(即不可见,禁用等)。所以在这些情况下,js帮助我(点击元素或获取元素的文本)。我喜欢js与不可见(禁用)元素交互的方式。恕我直言,我们不需要使用js作弊方法进行元素可见性(或启用/禁用)验证)

public void jsClickOnElement(String cssSelector){
        JavascriptExecutor js = (JavascriptExecutor) driver;
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("var x = $(\'"+cssSelector+"\');");
        stringBuilder.append("x.click();");
        js.executeScript(stringBuilder.toString());

    }