前言 我们已经学习了PageObject设计模式,优势很明显,能更好的体现java的面向对象思想和封装特性。但同时也存在一些不足之处,那就是随着这种模式使用,随着元素定位获取,元素定位与页面操作方法都在一个类里维护,会造成代码冗余度过高。 相信使用过spring的同学肯定都知道,基于注解方式的开发,会大大提高开发效率,使代码块变得相对整洁,清晰。 本文要介绍的就是PageFactory设计模式,同PageObject思想大体差不多,只是表现形式不太一样,只是通过注解方式来定位元素对象。一、FindBy和CacheLookup用法 元素声明的写法:定位密码输入框FindBy(nameloginpassword)CacheLookupprivateWebElementpassWord; 注解说明: FindBy:这个注解的意思是说我们所查找的元素是以什么方式定位, CacheLookup:这个注解的意思是说找到元素之后将缓存元素,重复的使用这些元素,将会大大加快测试的速度。 WebElementpassWord:就是变量名二、PageFactory类使用 PageFactory提供的是静态方法,可以直接调用,一般在用完FindBy后,需要进行元素初始化,则需要调用initElements(driver,this);方法。三、使用PageFactory模式来分离页面元素 此处演示还沿用pageobject模式的风格,这里我又加了一层自己暂时定义叫基础层,现在就变成了四层:基础层:用来存放driver及初始化使用。对象层:用于存放页面元素定位和控件操作。操作层:则是一些封装好的功能用例模块。业务层:则是我们真正的测试用例的操作部分。 下面将举例说明PageObject设计模式,我们还有360影视页面为例,来做进一步讲解。 1、基础层 先创建一个包,名为com。pagefactory。demo,接着在这个包下创建一个类名为HomePage,具体示例代码如下:importorg。openqa。selenium。WebDriver;importorg。openqa。selenium。chrome。ChromeDriver;importorg。openqa。selenium。support。PageFactory;authorrongrong基础页面publicclassHomePage{privatestaticWebDriverdriver;用来传递WebDriverreturnpublicstaticWebDriverdriver(){returndriver;}publicHomePage(){设置系统变量,并设置chromedriver的路径为系统属性值System。setProperty(webdriver。chrome。driver,toolchromedriver。exe);实例ChromeDriverdrivernewChromeDriver();PageFactory。initElements(driver,this);}打开浏览器publicvoidopen(){driver。get(https:i。360kan。comlogin);}关闭浏览器publicvoidclose(){driver。quit();}publicLoginPageloginPage(){LoginPageloginPagenewLoginPage();returnloginPage;}} 这是我的基础页面,为了让driver抽离出去 2、对象层 接着我们再来创建一个类,名为LoginPage,具体示例代码如下:importorg。openqa。selenium。WebElement;importorg。openqa。selenium。support。CacheLookup;importorg。openqa。selenium。support。FindBy;importorg。openqa。selenium。support。How;importorg。openqa。selenium。support。PageFactory;authorrongrong对象库层代码案例publicclassLoginPage{publicLoginPage(){PageFactory。initElements(HomePage。driver(),this);}定位用户名输入框FindBy(howHow。NAME,usingloginname)第一种写法CacheLookupprivateWebElementuserName;定位密码输入框FindBy(nameloginpassword)第二种写法CacheLookupprivateWebElementpassWord;定位登录按钮FindBy(linkText立即登录)CacheLookupprivateWebElementloginBtn;定位提示错误信息FindBy(css〔classbsigninerrorjsbsigninerrorerror2〕)CacheLookupprivateWebElementerrorMsg;publicWebElementgetUserName(){returnuserName;}publicWebElementgetPassWord(){returnpassWord;}publicWebElementgetLoginBtn(){returnloginBtn;}publicWebElementgetErrorMsg(){returnerrorMsg;}用户名输入操作paramuserNamepublicvoidsendKeysUserName(StringuserName){getUserName()。clear();getUserName()。sendKeys(userName);}密码输入操作parampassWordpublicvoidsendKeysPassWord(StringpassWord){getPassWord()。clear();getPassWord()。sendKeys(passWord);}} 3、操作层 接着我们再来创建一个类,名为LoginMovies,用来记录登录的一系列操作,具体示例代码如下:packagecom。demo;importorg。testng。Assert;authorrongrong操作层代码案例publicclassLoginMovies{登录过程paramuserNameparampwdparamexpectedpublicvoidloginByPageFactory(StringuserName,Stringpwd,Stringexpected){HomePagehomePagenewHomePage();打开登录页homePage。open();输入用户名homePage。loginPage()。sendKeysUserName(userName);输入密码homePage。loginPage()。sendKeysPassWord(pwd);点击登录homePage。loginPage()。getLoginBtn()。click();获取提示语操作StringmsghomePage。loginPage()。getErrorMsg()。getText();验证输入手机号错误是否提示Assert。assertEquals(msg,expected);关闭浏览器homePage。close();}} 4、业务层 最后我们再来创建一个类,名为TestPageFactory,用来验证登录功能,具体示例代码如下:importorg。testng。annotations。Test;authorrongrong业务层代码案例publicclassTestPageFactory{测试登录TestpublicvoidtextLogin(){实例化操作对象LoginMoviesloginMoviesnewLoginMovies();登录操作loginMovies。loginByPageFactory(youruserName,yourpassWord,输入手机号不合法);}} 从以上代码看,如果页面元素发生变化,我们在对应类里修改对应元素即可,而操作和业务层流程类及用例都不用改,如果仅是业务流程更改,只需要维护业务层流程类业务脚本,其他几个类都不用改,从而做到了很好的将页面、元素、脚本进行了分离。