我一直在使用@FindBy
一段时间了,我喜欢这样一个事实:元素直到必要时才会找到(不是实例化)。
但是,网页可能有2-10个特定元素,并且元素上的id已编号(因此第一个元素的id为“element1”等等)
我想写一个函数,我可以传入一个整数,它将返回一个具有相应ID的WebElement, AND 被懒惰地实例化。这意味着拥有如下功能将不起作用:
public WebElement getElement(int numOnPage){
return driver.findElement(By.id("element"+numOnPage));
}
因为即时我调用WebElement定位的函数。 (它无法实例化的原因是因为我有一个函数,通过一遍又一遍地调用isDisplayed()来等待元素存在,捕获NoSuchElementException
s。。
我也意识到我可以创建一个List<WebElement>
,通过CSS选择ID以“element”开头的每个元素,但我还有其他情况,我想要返回一个动态生成的元素,并且不得不也可以在那里使用解决方法。
谢谢!
答案 0 :(得分:1)
首先,我真的不明白为什么在元素确实在页面之前你绝对需要获得WebElement
引用。在正常情况下,您可以检查页面是否已完全加载,然后查找WebElement
。首先,通常会使用循环和NoSuchElementException
的catch来完成,如您所述。
但是,如果在页面中找不到WebElement
之前需要WebElement
的引用,我只需创建一个代理,该代理可以懒惰地加载(仅在第一次需要时)真实{{1}实例。像这样:
public WebElement getElement(final int numOnPage) {
return (WebElement) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class<?>[] { WebElement.class }, new InvocationHandler() {
// Lazy initialized instance of WebElement
private WebElement webElement;
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if (webElement == null) {
webElement = driver.findElement(By.id("element" + numOnPage));
}
return method.invoke(webElement, args);
}
});
}
通过调用getElement
,您可以检索WebElement
类型的对象。只要您调用其中一个方法,就会使用WebDriver.findElement
检索它。请注意,如果您在代理实例上调用方法,则该元素必须位于页面中,否则您将获得NoSuchElementException
。
答案 1 :(得分:1)
如果我正确理解了这个问题,你就不能用@FindBy注释做到这一点。问题是Java中的Annotations在编译期间被处理,因此您无法动态修改它们:
http://docs.oracle.com/javase/tutorial/java/annotations/
然而,听起来您的问题可以通过使用明确的等待轻松解决:
public WebElement getElement(int numOnPage){
WebDriverWait waiting= new WebDriverWait(driver, 15, 100);
return waiting.until(ExpectedConditions.visibilityOfElementLocated(By.id("element"+numOnPage)));
}
这将扫描页面,等待元素存在并且可见,以及何时向您返回WebElement。