利用反射简单模拟Spring的控制反转(Ioc)和依赖注入(DI)


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();
	}
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值