如何返回一个延迟实例化的动态webelement

我一直在使用@FindBy一段时间了,而且我喜欢这个元素直到它必要时才被定位的事实(不是实例化)。

但是,网页可能有2-10个特定元素,并且元素上的id已编号(因此第一个元素的id为“element1”,依此类推)

我想写一个函数,我可以传入一个整数,它将返回一个具有适当ID的WebElement, 并且是懒惰实例化的。 这意味着具有以下function将无法正常工作:

 public WebElement getElement(int numOnPage){ return driver.findElement(By.id("element"+numOnPage)); } 

因为即时我调用WebElement定位的函数。 (它无法实例化的原因是因为我有一个函数,通过一遍又一遍地调用isDisplayed()来等待元素存在,捕获NoSuchElementException s)。

我也意识到我可以创建一个List ,它通过CSS选择ID以“element”开头的每个元素,但我还有其他情况需要返回动态生成的元素,并且必须在那里使用变通方法同样。

谢谢!

首先,我真的不明白为什么你必须在元素真正在页面之前获得WebElement引用。 在正常情况下,您可以检查页面是否已完全加载,然后查找WebElement 。 首先,通常会使用循环和NoSuchElementException的catch来完成,如您所述。

但是,如果在页面中找不到WebElement之前需要WebElement的引用,我只需创建一个代理,该代理可以懒惰地加载(仅在第一次需要时)真正的WebElement实例。 像这样的东西:

 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

如果我正确理解了这个问题,你就不能用@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。