0

我编写了一个简单的方法来检查是否启用了 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 属性来定位锚元素,该属性是 id=top-nav 的 div 的后代。不应该像我正在使用的那样为 ChromeDriver 工作的 CSS 定位器吗?有谁知道为什么像 findElements 这样的方法会抛出 InvalidElementStateExceptions?提前致谢!

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

附录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\" }, {\"元素\": \":wdc:1347370086857\"}, {\"元素\": \":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' 系统信息: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。

4

2 回答 2

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

但在使用这种方法之前,我建议您使用流利的等待。Fluent wait 返回您通过定位器找到的 web 元素(注意:如果 fluent wait 失败,那么您最好注意您的 xpath 或 neded 元素的 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;              }     ;

关于流利的等待我建议你在这里阅读

关于你找到 cssSelector 的方式坦率地说我也不喜欢它。而不是"div#top-nav a[href~=CorpAdmin/DisplayInformation]" 更好地尝试这个 div[id='top'] nav a[href~='CorpAdmin/DisplayInformation'] 并且总是用css或xPAth检查你的本地化元素(例如在firepath中,firefox addon to firebug)。见下图: 火路定位

希望这对您有所帮助。

于 2012-09-11T16:36:14.613 回答
1

顺便说一句,我遇到了类似的问题,但有这样的例外。 Selenium webcrawling 组合框 所以这种问题意味着你遇到了 selenium 无法与之交互的元素(即不可见、禁用等)。因此,在这些情况下,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());

    }
于 2012-09-12T09:11:35.280 回答