1

如果 Selenium2 在有限时间轮询后无法检索 WebElement 对象,我有这个想法,即故障转移到 JavascriptExecutor。如您所见,该方法具有在调用 getElementByLocator 时需要预先定义“故障转移”Javascript 片段的限制。我想不出任何方法来动态地做到这一点。如果有人可以帮助我改进这一点,我将奖励最佳建议的答案,无论它多么小。

// failover example1: "document.getElementById('gbqfb')"
// failover example2: "document.querySelector("div#gbqfb")"
public static WebElement getElementByLocator(final By locator, String failover) {
  Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
    .withTimeout(30, TimeUnit.SECONDS)
    .pollingEvery(5, TimeUnit.SECONDS);
    .ignoring(NoSuchElementException.class,StaleElementReferenceException.class);
  WebElement we = wait.until( ExpectedConditions
      .presenceOfElementLocated( locator ) );
  if ( we.isNull() ) {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    if ( !failover.isEmpty() ) {
      we = (WebElement)js.executeScript( failover );
      if ( we.isNull() ) LOG.info("Still couldn't get element.");
    } else {
      LOG.info("No failover String available.  Cannot try with " +
        "a JavascriptExecutor.");
    }    
  }
  return we;
}
4

1 回答 1

0

实际上在这里回答了一个类似的问题

我不建议像那样将任何东西委托给 javascript.. 使用 Selenium 给你的东西.. 就足够了。

我在我曾经构建的每一个框架中都放入了一些东西,这非常有效。这是从这里找到的框架的摘录。

在对对象执行任何操作之前,我实现了一种伪等待类型的方法。自己试试。这是非常有效的。

这些是来自AutomationTest类的方法

/**
 * Checks if the element is present or not.<br>
 * @param by
 * @return <i>this method is not meant to be used fluently.</i><br><br.
 * Returns <code>true</code> if the element is present. and <code>false</code> if it's not.
 */
public boolean isPresent(By by) {
    if (driver.findElements(by).size() > 0) return true;
    return false;
}

/**
 * Private method that acts as an arbiter of implicit timeouts of sorts.. sort of like a Wait For Ajax method.
 */
private WebElement waitForElement(By by) {
    int attempts = 0;
    int size = driver.findElements(by).size();

    while (size == 0) {
        size = driver.findElements(by).size();
        if (attempts == MAX_ATTEMPTS) fail(String.format("Could not find %s after %d seconds",
                                                         by.toString(),
                                                         MAX_ATTEMPTS));
        attempts++;
        try {
            Thread.sleep(1000); // sleep for 1 second.
        } catch (Exception x) {
            fail("Failed due to an exception during Thread.sleep!");
            x.printStackTrace();
        }
    }

    if (size > 0) System.err.println("WARN: There are more than 1 " + by.toString() + " 's!");

    return driver.findElement(by);
}

我所做的,是任何时候我做某事,比如

getText(By.cssSelector("input#someId"))

如果第一次没有找到,它会等待 1 秒。如果找到它,则继续。随后执行 5 次,因此总共等待 5 秒.. 这完全可以,因为如果您没有找到所需的元素,那么您的测试实际上应该在那时失败。

另外,根据经验,我可以告诉你,使用driver.findElements()比那些更有效WebDriverWait

这并不意味着我不使用它们.. 只是不是为了那个。不幸的是,我没有在 selenium 框架入门中添加这个功能,所以我会告诉你我什么时候使用 Webdriverwait 的。

所以我的测试看起来像 -

@Config(url="http://systemunder.test", browser=CHROME)
public class MyClass extends AutomationTest {

    @Test
    public void testSomething() {
        setText(By.id("blah")) // if <* id="blah" /> doesn't exist, waits 1+ seconds for it to appear before interacting.
        .click(By.id("Blah2")) // ^ same thing here.
        .waitForPresent(By.cssSelector("ajaxy")); // this method right here would circumvent the hard waits, with webdriverwait's.
    }
}

我不记得为什么它以前对我不起作用,但是在类似的情况下使用 webdriverwaits 是完美的。

于 2013-10-10T03:24:20.173 回答