之前写的自动化测试框架(PageObject设计思路)一直都是每执行一条用例,启动一次浏览器驱动就打开一次浏览器,一条用例执行结束之后就关闭浏览器。这样做不仅浪费时间而且每次都重启关闭chromedriver.exe也挺浪费资源的。所有根据TestNG生命周期的各个注解的执行顺序,对相关方法做了一点点的改动,实现了这一功能。
首先看一下PageFactory类,这个类主要是利用Java反射的机制,调用页面类的构造方法生成一个新的页面对象,这里我在这个类里面定义了一个WebDriver对象,以后这个driver对象将作为所有通过PageFactory类生成的页面对象的统一driver,理论上就实现了只存在一个driver对象的情景,代码如下:
PageFactory:
public class PageFactory { private static WebDriver driver; public static WebDriver getDriver() { return driver; } public static void setDriver(WebDriver driver) { PageFactory.driver = driver; } static Log log = new Log(PageFactory.class); /** * @Description: 生成新页面 * @param key * @return Object * @Author: zither */ public synchronized static Object getPage(Class<?> key) { Object obj = null; try { String pageClassName = key.getCanonicalName(); log.debug("跳转至页面 " + key.getSimpleName()); Class<?> clazz = Class.forName(pageClassName); try { Constructor<?> constructor = clazz.getConstructor(WebDriver.class); obj = constructor.newInstance(getDriver()); } catch (InstantiationException e) { log.error(e.getMessage()); e.printStackTrace(); } catch (IllegalAccessException e) { log.error(e.getMessage()); e.printStackTrace(); } } catch (Exception e) { } return obj; } }
然后我创建了一个TestSuite类,这个类是TestNG类,主要用来包含一些公用的@BeforeSuite,@AfterSuite等等,之后的每一TestNG类就可以直接继承这个类不用重复写这些注解了,
这里特别关注@BeforeSuite和@BeforeMethod里做了什么,代码如下:
TestSuite:
public class TestSuite { public static WebDriver driver; /** * @Description: 创建driver,将driver给到PageFactory页面工厂 * @return void * @Author: zither */ @BeforeSuite public void beforeSuite() { driver = DriverFactory.getChromeDriver(); PageFactory.setDriver(driver); } @BeforeMethod public void BeforeMethod() { driver.get(Config.URL); } /** * @Description: Suite结束关闭浏览器,结束驱动 * @return void * @Author: zither */ @AfterSuite public void afterSuite() { DriverFactory.close(driver); } }
再来看看Action类怎么写,Action业务流里的页面对象通过已经获得了driver的PageFactory来生成的话,就可以直接获得类似于复制出来的唯一driver了,但实际上还是只有一个driver在操作浏览器和页面,Action类写法如下(以打开浏览器进入主页,点击登录,进入登录页,登录,返回主页的业务流为例):
HomeAc
public class HomeAc { static HomePg homePg; /** * @Description: xxxx首页点击登录进入登录页 * @return LoginPg * @Author: zither */ public static LoginPg homeToLogin() { homePg = (HomePg) PageFactory.getPage(HomePg.class); homePg.clickLogin(); return (LoginPg) PageFactory.getPage(LoginPg.class); }
}
LoginAc
public class LoginAc { static LoginPg loginPg; /** * @Description: 登录页登录返回xxxx主页 * @param account * @param password * @return HomePg * @Author: zither */ public static HomePg LoginToHomePg(String account,String password) { loginPg = HomeAc.homeToLogin(); loginPg.typeAccount(account); loginPg.typePassword(password); loginPg.clickSubmit(); return (HomePg) PageFactory.getPage(HomePg.class); } }
如此一来我们的@Test每执行完一个用例,就会因为@BeforMethod里面在地址栏重新打开一次主页链接而回到主页,继续开始执行下一条用例,而不用去关掉浏览器再重启浏览器这么麻烦啦~~
其实这样做只针对一开始进入的是主页需要点击登录再进行登录的页面,因为这种网站登陆一次之后刷一下URL还是主页可以直接进行下一条用例的操作且不用再登陆了。
下一篇讲一讲,URL直接进入的是“登录页-->主页”而不是“主页-->登录-->主页”的网站该怎么操作~~