1.配置文件(.properties)中配置要扫描的包:
#扫描page对象的包
init.pageobj.Package = ec.qa.autotest.ui.admin.portal.pageobject,ec.qa.autotest.ui.common.action,ec.qa.autotest.ui.supplier.portal.pageobject
2.代码实现:
自定义2个标签:
@PageObject @AutoInject:
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author xin.wang
* @see 标识当前类是否是页面对象
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PageObject {
boolean lazyLoad() default false;
}
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author xin.wang
* 自动装配标签
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AutoInject {
boolean enable() default true;
}
package ec.qa.autotest.ui.utility;
import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import ec.qa.autotest.ui.custom.annotation.AutoInject;
import ec.qa.autotest.ui.custom.annotation.PageObject;
import ec.qa.autotest.ui.testbase.TestBase;
/**
* @author xin.wang
* 1.模拟IOC容器 通过反射扫描配置好的pageobject包并将 pageobject实例存放到全局静态MAP中。
* 2.实现了依赖注入功能 DI
*/
public class initPageObject {
private static Field[] fields = null;
private Object pageobj;
private String packAgePref = "src\\main\\java\\";
public initPageObject(Object ob) {
this.pageobj = ob;
<strong><span style="color:#ff0000;">PageObjectUtil.setPageObjMap(initPageObjMap()); //将页面对象存放到MAP中,MAP充当一个bean容器</span></strong>
}
private HashMap<String, Object> initPageObjMap() {
HashMap<String, Object> pageobjs = new HashMap<String, Object>();
HashSet<String> fieldSet = new HashSet<String>();
String curClassName = TestBase.getTestCaseDeclaringClass();
try {
String[] packagePath = PropertiesUtil.getProValue("init.pageobj.Package").split(",");
fields = Class.forName(curClassName).getDeclaredFields();
fillFieldNameSet(fields, fieldSet);
for (String pp : packagePath) {
ArrayList<String> classNames = new ArrayList<String>();
getClassName(packAgePref + pp.replace(".", "\\"), classNames, pp);
for (String className : classNames) {
Class<?> classObj = Class.forName(className);
if (classObj.getAnnotation(<span style="color:#ff0000;">PageObject.class</span>) != null
&& fieldSet.contains(classObj.getSimpleName())) {
pageobjs.put(classObj.getSimpleName(), classObj.newInstance());
}
}
}
injectPageObj(fields, pageobjs);
} catch (Exception e) {
e.printStackTrace();
}
return pageobjs;
}
/**
* @author xin.wang
* @param fields
* @param pageobjs
* @throws IllegalArgumentException
* @throws IllegalAccessException
*实现向测试用例类自动注入页面对象的功能
*/
private void injectPageObj(Field[] fields, HashMap<String, Object> pageobjs)
throws IllegalArgumentException, IllegalAccessException {
for (Field f : fields) {
f.setAccessible(true);
f.set(pageobj, pageobjs.get(f.getType().getSimpleName()));
f.setAccessible(false);
}
}
private void fillFieldNameSet(Field[] fields, HashSet<String> fieldSet) {
for (Field f : fields) {
if (f.getAnnotation(<span style="color:#ff0000;">AutoInject.class</span>) != null) {
fieldSet.add(f.getType().getSimpleName());
}
}
}
private ArrayList<String> getClassName(String folderPath, ArrayList<String> className, String packageName)
throws Exception {
File files = new File(folderPath);
for (File f : files.listFiles()) {
if (f.isFile() && f.getName().endsWith(".java")) {
className.add(packageName + "." + f.getName().substring(0, f.getName().indexOf(".")));
}
}
return null;
}
}
3.如何使用上面的功能:由于测试用例的运行调度使用的是testng所以需要几个testng的机制来使用,在testng实例化当前测试用例所在类的时候进行注入:
示例:
@BeforeMethod
public void initTestCase(){
new initPageObject(this); //将当前对象传给注入功能类 对此实例中标有@AutoInject的类成员进行注入
}
实例:
public void configDriver(ConfigDriverParameters cp) throws Exception {
testCaseDeclaringClass = cp.getTestMethod().getDeclaringClass().getName();
String website = cp.getTargetWebSite();
if (!success) {
System.out.println("\n=======测试用例准备重试=======");
reTryCount++;
success = true;
}
System.out.println("\n======测试用例: " + cp.getTestMethod().getName() + " 开始执行======" + "\n===测试用例运行的浏览器类型:"
+ browserType + " ===" + "\n测试网站地址: " + website);
webDriver = DriverUtil.getWebDriver(browserType);
<strong><span style="color:#ff0000;">new initPageObject(this); //关键点在此 其他忽略</span></strong>
webDriver.manage().timeouts().implicitlyWait(cp.getSerachElementTime(), TimeUnit.SECONDS);
webDriver.manage().window().maximize();
webDriver.manage().timeouts().pageLoadTimeout(cp.getPageLoadTime(), TimeUnit.SECONDS);
if (CookiesUtil.getCk() != null) {
webDriver.manage().timeouts().pageLoadTimeout(3, TimeUnit.SECONDS);
try {
webDriver.get(website);
} catch (Exception e) {
}
webDriver.manage().addCookie(CookiesUtil.getCk());
}
try {
webDriver.get(website);
} catch (Exception e) {
}
webDriver.manage().timeouts().pageLoadTimeout(-1, TimeUnit.SECONDS);
}
测试页面对象类实例:
package ec.qa.autotest.ui.admin.portal.pageobject;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.support.PageFactory;
import ec.qa.autotest.ui.custom.annotation.PageObject;
import ec.qa.autotest.ui.testbase.TestBase;
/**
* @author xin.wang
* @see 登录页面
*/
@PageObject
public class AdminPortalLoginPage {
@FindBy(how = How.ID, using = "loginname")
private WebElement userNameInputBox;
@FindBy(how = How.ID, using = "password")
private WebElement passwordInputBox;
@FindBy(how = How.NAME, using = "loginForm")
private WebElement submitButton;
public void setUserNameContent(String username) {
userNameInputBox.click();
userNameInputBox.sendKeys(username);
}
public void setPwdContent(String pwd) {
passwordInputBox.click();
passwordInputBox.sendKeys(pwd);
}
public void getUserNameContent(String username) {
userNameInputBox.getText();
}
public String getUserNameContent() {
return userNameInputBox.getText();
}
public AdminPortalLoginPage(){
PageFactory.initElements(TestBase.getWebDriver(), this);
}
/**
* @author xin.wang
* @see 登录后台管理系统
*/
public void loginAdminPortal(String username, String pwd) {
setUserNameContent(username);
setPwdContent(pwd);
submitButton.submit();
}
}
测试用例类实例:
package ec.qa.autotest.ui.admin.portal.testcases;
import org.testng.AssertJUnit;
import org.testng.annotations.Test;
import ec.qa.autotest.ui.admin.portal.pageobject.AdminPortalLoginPage;
import ec.qa.autotest.ui.admin.portal.pageobject.NavigationMenu;
import ec.qa.autotest.ui.custom.annotation.AutoInject;
import ec.qa.autotest.ui.testbase.AdminPortalTestBase;
/**
*
* @auther xin.wang
*登录后台管理系统
*/
public class LoginAdminPortal extends AdminPortalTestBase{
@AutoInject
private AdminPortalLoginPage ecHomePage;
@AutoInject
private NavigationMenu ctPage;
@Test
public void loginAdminPortal() throws Exception{
ecHomePage.loginAdminPortal("admin", "111111");
AssertJUnit.assertEquals(ctPage.getWelcomeContent(), "欢迎您,");
AssertJUnit.assertEquals(ctPage.getCurLoginUser(), "超级管理员");
ctPage.goToProdcutLibPage();
}
}
4.既然实现了IOC容器,那么我在必要情况下可以手动拿到当前测试需要的页面类对象:在 initPageObject 类中 标红部分既是向容器中注入页面对象实例的过程,通过调用如下代码 在测试用例中可随意拿出页面对象进行操作:
package ec.qa.autotest.ui.utility;
import java.util.HashMap;
/**
* @author xin.wang
* 获取页面对象的工具类
*/
public class PageObjectUtil {
private static HashMap<String, Object> pageobjs = null;
public static void setPageObjMap(HashMap<String, Object> Map){
pageobjs = Map;
}
@SuppressWarnings("unchecked")
public static <T> T getPageObject(String pageObjectClassName){
return (T)pageobjs.get(pageObjectClassName);
}
}
用例中调用 PageObjectUtil .getPageObject("pageobjectclassname") 即可.
public class LoginAdminPortal extends AdminPortalTestBase{
@AutoInject
private NavigationMenu ctPage;
@Test(invocationCount = 1)
public void loginAdminPortal() throws Exception{
AssertJUnit.assertEquals("欢迎您,",ctPage.getWelcomeContent());
AssertJUnit.assertEquals("超级管理员1",ctPage.getCurLoginUser());
ctPage.goToProdcutLibPage();
ctPage =PageObjectUtil.getPageObject("NavigationMenu");
ctPage.clickProdcutCenterMenu();
}
}