Wait.until()与Webdriver PageFactory元素

时间:2012-03-30 07:52:38

标签: java webdriver selenium-webdriver

我正在使用@FindBy注释来查找我页面上的元素。像这样:

   @FindBy(xpath = "//textarea")
    public InputBox authorField;

请帮忙。我希望使用带有注释元素的wait(ExpectedConditions)。像这样:

wait.until(visibilityOfElementLocated(authorField));

而不是:

wait.until(visibilityOfElementLocated(By.xpath("//textarea")));

感谢您提前

4 个答案:

答案 0 :(得分:5)

问题是采用WebElement的方法通常假设WebElement已经找到(并且它们是正确的!PageFactory将它排列在一个方法访问元素之前,它被发现。),即存在于页面上。当给方法一个By时,你说“我希望它被找到,我只是不知道它什么时候会出现。”

您可以使用

wait.until(visibilityOf(authorField));

结合
// right after driver is instantiated
driver.manage().timeouts().implicitlyWait(...);

这应该按照你想要的方式来做。

implicitlyWait() documentation说:

  

指定驱动程序在搜索元素时应等待的时间(如果元素不立即存在)。

     

当搜索单个元素时,驱动程序应轮询页面,直到找到该元素,或者在抛出NoSuchElementException之前此超时到期。搜索多个元素时,驱动程序应轮询页面,直到找到至少一个元素或此超时已过期。

所以,基本上,它每次查找时都会等待一个元素出现。这显然适用于所有类型的异步请求。

答案 1 :(得分:4)

ExpectedConditions.visibilityOf(authorField);

查看任何预期条件的源代码。编写自己的条件非常容易,可以做你想做的一切。

答案 2 :(得分:3)

我知道这个问题已经回答了,不久之前就被问过了,但我想我会提供一个具体的例子来说明如何为此编写自己的预期条件。通过创建此预期条件类:

/**
 * Since the proxy won't try getting the actual web element until you
 * call a method on it, and since it is highly unlikely (if not impossible)
 * to get a web element that doesn't have a tag name, this simply will take
 * in a proxy web element and call the getTagName method on it. If it throws
 * a NoSuchElementException then return null (signaling that it hasn't been
 * found yet). Otherwise, return the proxy web element.
 */
public class ProxyWebElementLocated implements ExpectedCondition<WebElement> {

    private WebElement proxy;

    public ProxyWebElementLocated(WebElement proxy) {
        this.proxy = proxy;
    }

    @Override
    public WebElement apply(WebDriver d) {
        try {
            proxy.getTagName();
        } catch (NoSuchElementException e) {
            return null;
        }
        return proxy;
    }

}

然后这将允许你这样做:

wait.until(new ProxyWebElementLocated(authorField));

这就是你真正需要的。但是如果你想进一步抽象,你可以创建一个这样的类:

public final class MyExpectedConditions {

    private MyExpectedConditions() {}

    public static ExpectedCondition<WebElement> proxyWebElementLocated(WebElement proxy) {
        return new ProxyWebElementLocated(proxy);
    }
}

然后你可以做这样的事情:

wait.until(MyExpectedConditions.proxyWebElementLocated(authorField));

对于一个预期条件,MyExpectedConditions类可能有点矫枉过正,但如果你有多个预期条件,那么拥有它会使事情变得更好。

作为任何真正想要加倍努力的最后一点,您还可以向MyExpectedConditions类添加方法,将方法包装在ExpectedConditions类中,然后您就可以获得所有方法您在一个地方的预期条件。 (我建议扩展ExpectedConditions而不是使用包装器方法,但它有一个私有构造函数,因此无法扩展。这使得包装器方法成为那些真正想要在一个地方放置所有内容的人的唯一选择。)

答案 3 :(得分:0)

如其他答案中所述,ExpectedConditions.visibilityOf(authorField);将胜任。在下面提到一个详细的解决方案,以使其更加清晰。

public class YourTestPage {
    private WebDriver driver;
    private WebDriverWait wait;

    @FindBy(xpath = "//textarea")
    private WebElement authorField;

    public YourTestPage(WebDriver driver) {
        this.driver = driver;
        wait = new WebDriverWait(driver, 15, 50);
        PageFactory.initElements(driver,this);
    }

    public void enterAuthorName() {
        wait.until(ExpectedConditions.visibilityOf(authorField)).sendKeys("Author Name");
    }
}