第二节里我们介绍了iunit整体的设计思路以及核心类之间的关系,这篇将以源码+解释的方式来演示核心类的实现方式
1. IUnitRunner类
这个类是测试的入口类,直接继承自junit4。8的BlockJunit4ClassRunner,在构造函数里,我们把iunit框架的扩展功能添加了进来,因为整个框架呃设计都是基于Listener的,所以只需要把监听器在框架运行的时候加载进来即可--见构造函数,listener的注册是通过注解来进行的,因为测试类本身可能会有继承关系,因此需要遍历父类中的Listener,把子类+所有父类中的Listener合并起来,当然还要注意剔除掉重复注册的Listener,否则很可能导致一个Listener被执行多次(既在子类中注册过了又在父类中注册过了)
package com.crazycoder2010.iunit; import java.util.ArrayList; import java.util.List; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; import org.junit.runners.model.Statement; import com.crazycoder2010.iunit.annotation.IUnitTestExecuteListeners; public class IUnitRunner extends BlockJUnit4ClassRunner { /** * 监听器 */ private List<IUnitTestExecuteListener> executeListeners = new ArrayList<IUnitTestExecuteListener>(); private Class<?> clazz; private TestContext testContext; public IUnitRunner(Class<?> klass) throws InitializationError { super(klass); //这个构造函数是junt的调用入口,这里我们把扩展功能的初始化写到其后 this.clazz = klass; this.testContext = new TestContext(); initListeners(); } private void initListeners(){ this.executeListeners.addAll(findListeners()); } /** * 解析为当前测试类注册的监听器 * @return */ @SuppressWarnings(“rawtypes”) private List<IUnitTestExecuteListener> findListeners(){ List<IUnitTestExecuteListener> result = new ArrayList<IUnitTestExecuteListener>(); List<Class> listeners = new ArrayList<Class>(); Class<?> c = this.clazz; while(c != null){ IUnitTestExecuteListeners listener = c.getAnnotation(IUnitTestExecuteListeners.class); if(listener != null){ for(Class<? extends IUnitTestExecuteListener> l : listener.value()){ if(!listeners.contains(l)){//去重 listeners.add(l); } } } c = c.getSuperclass();//查找父类中的监听器 } for(Class clazz:listeners){ try { result.add((IUnitTestExecuteListener) clazz.newInstance());//通过反射将Listener实例加入到监听列表中 } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } return result; } |