什么时候FindBy属性触发driver.FindElement?

时间:2014-02-12 09:29:29

标签: selenium selenium-webdriver webdriver pageobjects

我的问题是:用findby属性修饰的webelements是否在每次引用时调用findelement函数?如果没有,何时?

List<的过程是什么? webelement>哪个还装饰?当您引用列表时,或引用该列表中的元素时,它会触发吗?

我在问,因为我遇到了一些情况,我得到过时的元素异常,我想知道如何处理它们。

2 个答案:

答案 0 :(得分:3)

WebElements被懒惰地评估。也就是说,如果您从未在PageObject中使用WebElement字段,则永远不会为其调用“findElement”。 Reference

如果每次都不希望WebDriver查询元素,则必须使用@CacheLookup注释。

  

我的问题清单部分怎么样?

从列表中查询时会触发findElements。说你有:

@FindBy(xpath = "//div[@class=\"langlist langlist-large\"]//a")
private List<WebElement> list;

以下代码示例所有触发 findElements:

list.isEmpty();

WebElement element = list.get(0);

在哪里

List<WebElement> newList = new ArrayList<WebElement>();
newList = list;

不会触发 findElements()。

请查看LocatingElementListHandler课程。我建议潜入源头寻找答案。


您可以从PageFactory类中找到此代码注释:

/**
   * Instantiate an instance of the given class, and set a lazy proxy for each of the WebElement
   * and List<WebElement> fields that have been declared, assuming that the field name is also
   * the HTML element's "id" or "name". This means that for the class:
   * 
   * <code>
   * public class Page {
   *     private WebElement submit;
   * }
   * </code>
   * 
   * there will be an element that can be located using the xpath expression "//*[@id='submit']" or
   * "//*[@name='submit']"
   * 
   * By default, the element or the list is looked up each and every time a method is called upon it.
   * To change this behaviour, simply annotate the field with the {@link CacheLookup}.
   * To change how the element is located, use the {@link FindBy} annotation.
   * 
   * This method will attempt to instantiate the class given to it, preferably using a constructor
   * which takes a WebDriver instance as its only argument or falling back on a no-arg constructor.
   * An exception will be thrown if the class cannot be instantiated.
   * 
   * @see FindBy
   * @see CacheLookup
   * @param driver The driver that will be used to look up the elements
   * @param pageClassToProxy A class which will be initialised.
   * @return An instantiated instance of the class with WebElement and List<WebElement> fields proxied
   */

答案 1 :(得分:0)

对于问题1)“页面工厂”模式中的概念是仅在任何操作中使用WebElement时才标识它们。

对于问题2)无论何时尝试访问Page类变量(WebElement或List),@ FindBy都会根据变量类型触发FindElement或FindElements。

class LoginPage{
.....
@FindBy(id, "uname")
WebElement username;// no trigger

@FindBy(xpath, "//table/tr")
List<WebElement> pdtTable; // no trigger
.....
.....

public void enterUserame(String text){
    uname.sendKeys(text);
}

.....
.....
}

.....
.....
LoginPage loginPage = PageFactory
  .initElements(driver, LoginPage.class); // creates WebElement variables but not triggers


if(loginPage.uname.isDisplayed()){// Trigger happens
loginPage.enterUserame("example");// Trigger happens
}
int count=pdtTable.size();// Trigger happens for FindElements

其他信息:PageFactory批注@CacheLookup用于标记一旦定位的WebElement,以便始终可以使用DOM中的相同实例。当将此注释应用于WebElement时,它指示Selenium保留WebElement的缓存,而不是每次都从WebPage中搜索WebElement。这可以帮助我们节省很多时间。