原来写过的一篇WebElement元素过期的Blog,见下:
http://blog.sina.com.cn/s/blog_64693fd401012zoq.html
今天研究了org.openqa.selenium.support里面的东西
发现原来PageFactory可以避免元素过期的,例子见下:
首先定义两个一样的元素,其中一个由Locator指定;另一个由 @FindBy 注解修饰
By anyDealLocator =By.xpath("//h2[@class='deal-title']/a");
@FindBy(xpath = "//h2[@class='deal-title']/a") WebElementanyDealProxyed;
然后在构造函数里面调用
PageFactory.initElements(driver,this);
public HomePage(WebDriver driver)
{
this.driver = driver;
PageFactory.initElements(driver, this);
}
下面分别使用两个WebElment,看看效果?
其中按销量排序会使页面进行变化,导致原有的WebElement失效。
public void magic()
{
System.out.println(anyDealProxyed.getAttribute("title"));
driver.findElement(By.xpath("//a[text()='销量']")).click();//按销量排序
System.out.println(anyDealProxyed.getAttribute("title"));
}
结果:magic()方法 pass了;
public void magic2()
{
WebElement anyDeal = driver.findElement(anyDealLocator);
System.out.println(anyDeal.getAttribute("title"));
driver.findElement(By.xpath("//a[text()='销量']")).click();//按销量排序
System.out.println(anyDeal.getAttribute("title"));
}
结果:magic2()方法报错了;
//org.openqa.selenium.StaleElementReferenceExc
eption: Elementnot found in the cache - perhaps the page has changed since it waslooked up
回头来分析一下PageFactory这个玩意:
看一下initElement方法的JavaDoc:
Instantiate an instance of the given class, and set a lazyproxy for each of the WebElement and List fields that have beendeclared, assuming that the field name is also the HTML element's"id" or "name". This means that for the class:
public classPage { private WebElement submit; }
there will be an elementthat can be located using the xpath expression "//*[@id='submit']"or "//*[@name='submit']"
By default, theelement or the list is looked up each and every time a method iscalled upon it. To change this behaviour, simply annotatethe field with the
CacheLookup
. To change how the element is located, usethe
FindBy
annotation. This method will attempt toinstantiate the class given to it, preferably using a constructorwhich takes a WebDriver instance as its only argument or fallingback on a no-arg constructor. An exception will be thrown if theclass cannot be instantiated.
看到了吧,一旦page被PageFactory进行处理过,每一次操作的时候都会去更新其声明的WebElement使其是最新的。