5

我已经使用@FindBy了一段时间了,我喜欢这样一个事实,即元素只有在必要时才会被定位(而不是在实例化时)。

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

我想编写一个可以传入整数的函数,它将返回一个具有适当 ID 的 WebElement,并且被延迟实例化。这意味着具有以下功能将不起作用:

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

因为在我调用该函数的那一刻,WebElement 就被定位了。(它不能被实例化的原因是因为我有一个函数,它通过反复调用 isDisplayed() 来等待元素存在,捕获NoSuchElementExceptions)。

我也意识到我可以创建一个List<WebElement>通过 CSS 选择 ID 以“元素”开头的每个元素的方法,但我遇到过其他情况,我想返回一个动态生成的元素,并且也必须在那里使用解决方法。

谢谢!

4

2 回答 2

1

首先,我真的不明白为什么您绝对需要WebElement在元素真正出现在页面中之前获得参考。在正常情况下,您可以检查页面是否已完全加载,然后查找WebElement. NoSuchElementException正如您提到的,首先通常使用循环和捕获来完成。

WebElement但是,如果您需要在页面中找不到a 之前的引用,我将简单地创建一个代理,该代理会延迟加载(仅在第一次需要时)真实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.

于 2013-08-04T05:26:26.540 回答
1

如果我正确理解了这个问题,你不能使用 @FindBy 注释来做到这一点。问题是 Java 中的注解是在编译时处理的,因此您不能即时修改它们:

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 返回给您。

于 2013-08-04T09:37:19.993 回答