selenium目前比较流行的设计模式就是page object,那么到底什么是page object呢,简单来说,就是把页面作为对象,在使用中传递页面对象,来使用页面对象中相应的成员或者方法,能更好的提现java的面向对象和封装特性。而使用时间长了会发现该模式也存在一点问题,那就是元素每次都要获取,并且获取元素与页面方法不分离,增加代码冗余度,用过springMVC框架的人都知道,注解方式的开发会大大增加开发效率,使页面变得整洁。
本次要介绍的就是pageFactory 设计模式,什么是pageFactory 设计模式呢?
准确来说就是在page object模式基础上更好的利用了面向对象的思维,将获取元素与操作页面的方法进行分离,以前获取元素要findelementbyid等等,现在只要一个注解就可以搞定,并且再次跑自动化回归测试时候,代码有获取缓存的特性,所以会比第一次跑的快,只要id,name不变。
1.首先介绍FindBy类:
For example, these two annotations point to the same element:
@FindBy(id = "f") WebElement f;
@FindBy(how = How.ID, using = "f") WebElement f;
and these two annotations point to the same list of elements:
@FindBy(tagName = "a") List links;
@FindBy(how = How.TAG_NAME, using = "a") List links;
用来分别查找单个元素和多个元素的两种用法,支持的类型有:className、
css、
id、
linkText、
name、
partialLinkText、
tagName、
xpath。
How支持的类型和上面差不多。
2.接着介绍PageFactory类
Factory class to make using Page Objects simpler and easier.
它提供的方法都是静态的,可以直接调用,我们在用完findby后,需要进行元素初始化,则需要调用下面的方法
initElements(ElementLocatorFactory factory, java.lang.Object page)、initElements(FieldDecorator decorator, java.lang.Object page)、initElements(WebDriver driver, java.lang.Class
我们在实际使用中可以这样用:
PageFactory.initElements(dr, XXX.class);
或者
PageFactory.initElements(new AjaxElementLocatorFactory(dr, 10) ,XXX.class);
后者加入了初始化元素时等待时间。
3.下面给大家简单用个例子介绍我的设计模式。public class BasePage {
WebDriver driver;
private final int TIMEOUT=3;
public BasePage(WebDriver driver )
{
this.driver=driver;
PageFactory.initElements(new AjaxElementLocatorFactory(driver, TIMEOUT) , this);
}
public BasePage(WebDriver driver,final String title)
{
this.driver=driver;
WebDriverWait wait=new WebDriverWait(driver, TIMEOUT);
try{
boolean flag = wait.until(new ExpectedCondition
@Override
public Boolean apply(WebDriver arg0) {
// TODO Auto-generated method stub
String acttitle = arg0.getTitle();
return acttitle.equals(title);
}});
}catch(TimeoutException te) {
throw new IllegalStateException("当前不是预期页面,当前页面title是:" + driver.getTitle());
}
PageFactory.initElements(new AjaxElementLocatorFactory(driver, TIMEOUT) , this);
}
这是我的基础页面,以后任何页面都继承该页面,因为判断UI层次的页面标题。
2.登录页面
public class LoginPage extends BasePage {
@FindBy(id="ele_active_close")
@CacheLookup
private WebElement wd;
@FindBy(id="at_index_login-box_mobile")
@CacheLookup
private WebElement inputusername;
@FindBy(id="at_index_login-box_password")
@CacheLookup
private WebElement inputpassword;
@FindBy(id="at_index_login-box_p_forget_login")
@CacheLookup
private WebElement mybutton;
public LoginPage(WebDriver driver) {
// TODO Auto-generated constructor stub
super(driver);
}
public LoginPage(WebDriver driver, String title) {
super(driver, title);
// TODO Auto-generated constructor stub
}
//不设定homepage类型不行,因为返回的是这个对象 必须是这个类型
public HomePage login(){
JbClose();
username("");
password("");
mybutton();
return new HomePage(driver,"xxx);
}
public void username(String username)
{
inputusername.clear();
inputusername.sendKeys(username);
}
public void password(String password)
{
inputpassword.clear();
inputpassword.sendKeys(password);
}
public void mybutton()
{
mybutton.click();
}
public void JbClose()
{
wd.click();
}
}
3.登录后要进入什么页面
public class HomePage extends BasePage{
public HomePage(WebDriver driver) {
super(driver);
// TODO Auto-generated constructor stub
}
public HomePage(WebDriver driver,String title)
{
super(driver,title);
}
}
4.下面就是main方法了,实际中建议和testng混合使用
public class TestFactory {
public static void main(String[] args) {
WebDriver driver=new ChromeDriver();
driver.get("http://petrocoke-web-test.obaymax.com/");
String logintitle="xxx";
LoginPage lg=new LoginPage(driver, logintitle);
HomePage hm=lg.login();
System.out.println("测试结束");
driver.quit();
}
}
这种模式大大的降低了耦合度 并且用着很舒服,对面向对象编程也做了很好的诠释。