我的问题是:用 findby 属性装饰的 webelements 在每次引用它们时都会调用 findelement 函数吗?如果没有,什么时候?
以及同样被装饰的 List< webelement > 的程序是什么?它会在您引用列表时触发,还是在您引用该列表中的元素时触发?
我之所以问,是因为我在某些情况下会遇到过时的元素异常,我想知道如何处理它们。
我的问题是:用 findby 属性装饰的 webelements 在每次引用它们时都会调用 findelement 函数吗?如果没有,什么时候?
以及同样被装饰的 List< webelement > 的程序是什么?它会在您引用列表时触发,还是在您引用该列表中的元素时触发?
我之所以问,是因为我在某些情况下会遇到过时的元素异常,我想知道如何处理它们。
WebElements 被懒惰地评估。也就是说,如果您从未在 PageObject 中使用 WebElement 字段,则永远不会调用“findElement”。参考。
如果不想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)页面工厂模式中的概念是仅在WebElements用于任何操作时才对其进行识别。
对于问题 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。这可以帮助我们节省大量时间。