我有一个想法,如果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;
}

最佳答案

实际上回答了类似的问题here

我不建议将任何东西委托给javascript这样的东西。使用Selenium给您的东西就足够了。

我在我建立的每个框架中都放了一些东西,这非常有效。.这是从here找到的框架摘录的内容。

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

这些是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是完美的。

关于java - Selenium2 findElement失败时故障转移到JavascriptExecutor吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19286092/

10-13 00:34