如果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;
}
答案 0 :(得分:0)
实际上回答了类似的问题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是完美的。