我正在使用jBehave / Selenium进行自动化测试。
现在我使用以下代码在页面上获取可见元素;
public WebElement getVisibleElement( final By by, final WebElement parentElement, int timeoutValue, TimeUnit timeoutPeriod, int pollingInterval, TimeUnit pollingPeriod ) {
return fluentWait(timeoutValue, timeoutPeriod, pollingInterval, pollingPeriod).until( new Function<WebDriver, WebElement>(){
public WebElement apply(WebDriver driver) {
try{
WebElement element = parentElement.findElement(by);
if ( element.isDisplayed() ) {
return element;
} else {
return null;
}
} catch( NoSuchElementException e ) {}
return null;
}
} );
}
现在问题是,如果页面上没有该元素,Selenium会花费大量时间尝试在页面上找到它。 有什么方法可以优化代码,这样在这种情况下不会花费很长时间吗?
答案 0 :(得分:0)
首先,我认为你不应该通过调用findElement并捕获潜在的异常来检查元素是否存在。最好使用findElements并检查列表大小
public WebElement getElementIfPresent(By locator) {
driver.manage().timeouts().implicitlyWait(100, TimeUnit.MILLISECONDS);
List<WebElement> elements = driver.findElements(locator);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
if(!elements.isEmpty()) {
return elements.get(0);
}
else {
return null;
}
}
问题是WebDriver会隐式等待元素出现。因此,在执行上述代码之前,您可能希望通过将隐式等待时间设置为较低值来缩短时间。在对可能不存在的元素进行任何查找之前,必须先进行此操作。然后,您需要恢复原始隐式等待值,否则可能会影响剩余测试的稳定性。
最后,您只需使用isDisplayed()
检查可见度,就像您在示例中所做的那样。
答案 1 :(得分:0)
即使是更优化的解决方案 - 也可以使用findElements(locator).size()
...
/**
* 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 > 1) System.err.println("WARN: There are more than 1 " + by.toString() + " 's!");
return driver.findElement(by);
}
这个构建的方式是你在操作它之前调用它。像,
WebElement myElement = waitforElement(By.cssSelector("input#someInput"));
myElement.sendKeys("something");
这是一个经过验证的解决方案,我已经测试并积极地用于生产级回归测试系统。