第二节里我们介绍了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.Ignore;
import org.junit.internal.AssumptionViolatedException;
import org.junit.internal.runners.model.EachTestNotifier;
import org.junit.runner.Description;
import org.junit.runner.notification.RunNotifier;
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());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return result;
}
@Override
protected Object createTest() throws Exception {
Object testInstance = super.createTest();
//加上我们框架的扩展功能
this.testContext.setTestInstance(testInstance);
for(IUnitTestExecuteListener executeListener : this.executeListeners){
executeListener.prepareTestInstance(testContext);
}
return testInstance;
}
@Override
protected void runChild(FrameworkMethod method, RunNotifier notifier) {
EachTestNotifier eachNotifier= makeNotifier(method, notifier);
if (method.getAnnotation(Ignore.class) != null) {
runIgnored(eachNotifier);
} else {
runNotIgnored(method, eachNotifier);
}
}
private EachTestNotifier makeNotifier(FrameworkMethod method,
RunNotifier notifier) {
Description description= describeChild(method);
return new EachTestNotifier(notifier, description);
}
private void runIgnored(EachTestNotifier eachNotifier) {
eachNotifier.fireTestIgnored();
}
private void runNotIgnored(FrameworkMethod method,
EachTestNotifier eachNotifier) {
eachNotifier.fireTestStarted();
try {
Statement statement = methodBlock(method);
doBefore();
statement.evaluate();
doAfter();
} catch (AssumptionViolatedException e) {
eachNotifier.addFailedAssumption(e);
} catch (Throwable e) {
eachNotifier.addFailure(e);
testContext.setThrowable(e);
doAfterThrowable();
} finally {
eachNotifier.fireTestFinished();
}
}
private void doBefore()throws Exception{
for(IUnitTestExecuteListener executeListener : this.executeListeners){
executeListener.beforeTest(testContext);
}
}
private void doAfter() throws Exception{
for(IUnitTestExecuteListener executeListener : this.executeListeners){
executeListener.afterTest(testContext);
}
}
private void doAfterThrowable(){
for(IUnitTestExecuteListener executeListener : this.executeListeners){
try {
executeListener.afterThrowable(testContext);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
2.IUnitTestExecuteListener接口
这个接口定义了测试用例执行生命周期的几个关键点
package com.crazycoder2010.iunit;
/**
* 框架执行监听器
* @author Kevin
*
*/
public interface IUnitTestExecuteListener {
/**
* TestCase对象被加载后执行的操作,每个TestCase只会执行一次
* @param testContext
*/
public void prepareTestInstance(TestContext testContext) throws Exception;
/**
* 在每执行一个单元测试方法之前运行
* @param testContext
* @throws Exception
*/
public void beforeTest(TestContext testContext) throws Exception;
/**
* 每个单元测试方法执行完时执行
* @param testContext
* @throws Exception
*/
public void afterTest(TestContext testContext) throws Exception;
/**
* 发生异常时做的处理
* @param testContext
*/
public void afterThrowable(TestContext testContext) throws Exception;
}
3.IUnitTestExecuteListeners注解
这个用来给测试类注册监听器的注解,一个IUnitTestExecuteListeners可以注册多个Listener
package com.crazycoder2010.iunit.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.crazycoder2010.iunit.IUnitTestExecuteListener;
/**
* 为TestCase注册监听器
*
* @author Kevin
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@Documented
public @interface IUnitTestExecuteListeners {
/**
* 实际用到的监听器类
*
* @return
*/
Class<? extends IUnitTestExecuteListener>[] value() default {};
}
4.AbstractIUnitTestCase测试基类
这个类是为了便于测试定义了一个TestCase的基类,可以在此注册一些通用的监听器,注意@Runwith(IUnitRunner.class)这个是关键,否则我们写在runner中扩展的功能是不会被junit4执行到的
package com.crazycoder2010.iunit;
import org.junit.runner.RunWith;
import com.crazycoder2010.iunit.annotation.IUnitTestExecuteListeners;
@RunWith(IUnitRunner.class)
@IUnitTestExecuteListeners({DatasetProviderListener.class})
public class AbstractIUnitTestCase {
}
分享到:
相关推荐
框架核心 快速开发(基础功能全部由代码生成器生成) 支持前端、后台自定义业务代码扩展,后台提供了大量常用扩展与通用类 前端、后台提供了近300个扩展方法与属性,开发人员可在此功能上编写扩展自定义业务代码 代码...
Spring是一个开源开发框架,是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。 spring主要用来开发java应用,构建J2EE平台的web应用。其核心就是提供一种新的机制管理业务对象及其依赖关系 (2)spring的优点...
这些都预示着我们进入了一个新的互联网阶段web 2.0,它是相对web 1.0的新的一类互联网应用的总称,是一次从核心内容到外部应用的革命[10]。这个阶段发展迅速,互联网应用趋于多样化,其中变化最大的是由web 1.0网站...
DbHelperV2 - Teddy的通用数据库访问组件设计和思考 也论该不该在项目中使用存储过程代替SQL语句 如何使数据库中的表更有弹性,更易于扩展 存储过程——天使还是魔鬼 如何获取MSSQLServer,Oracel,Access中的数据字典...
Spring是一个开源开发框架,是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。 spring主要用来开发java应用,构建J2EE平台的web应用。其核心就是提供一种新的机制管理业务对象及其依赖关系 (2)spring的优点...
Spring是一个开源开发框架,是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。 spring主要用来开发java应用,构建J2EE平台的web应用。其核心就是提供一种新的机制管理业务对象及其依赖关系 (2)spring的优点...
执行脚本时,先提前创建一个数据库,数据库名:netcoredev EntityFramework Core3.1不再支持 Sqlserver2008,请使用2008以上的数据库或使用mysql 框架核心 快速开发(基础功能全部由代码生成器生成) 支持前端、...
工具类及通用代码模块 ├── mysite-article -- 文章模块 ├── mysite-base -- 标签页 ├── mysite-gatering -- 活动模块 ├── mysite-qa -- 问答模块 ├── mysite-user -- 招聘模块 技术选型 后端技术 ...
模式识别与智能计算的matlab实现源码Easy机器学习框架,库和软件(按语言)的精选列表。 如果您想为该列表做出贡献(请这样做),请向我发送拉取请求或与我联系。 另外,在以下情况下,不建议使用列出的存储库: ...
AspBox是一个方便快速开发ASP框架,AspBox提供了大量实用的ASP通用过程及方法和子类,可以简化大部分的ASP操作。AspBox还可以进行拓展子类对象以增强自身功能。封装严谨,层层嵌套,提高了代码重复利用多次利用。 ...
8.3 实现一个简单的媒体播放器 317 8.4 升级你的播放器 321 8.4.1 添加控制功能 321 8.4.2 添加拖放功能 325 8.4.3 添加音量调节功能 326 8.4.4 添加欢迎背景图片 328 8.5 系统效果展示 328 8.6 如何播放更多...
基于多个优秀开源项目,高度整合封装,提供了互联网项目常用的工具类,如:在线支付、阿里云OSS、消息队列、Redis缓存、短信验证、百度编辑器、微信SDK等 模块 funtl-framework-core 核心模块,主要提供开发所需的...
这个基于Python技术栈的Web应用程序项目源代码提供了一个通用的框架,使得学习者能够学习如何构建可扩展的管理系统。通过深入研究源代码,我们将了解使用Python进行Web应用开发的关键技术和实践方法。 项目的核心...
借此希望造一个轮子,已简化java web开发,开发者不需要学习更多的知识,只要一个框架就能解决绝大多数日常应用开发中的问题。由于诞生了这个框架,暂且取名为:ET-Framework (来自外星人的框架) 目标与计划 (1)...
上面的例子是一个用 Oea.svg 构建的工作计算器。 更多示例请点击 Java.js 该包包含许多实现 Draw2D.svg 和 Swing.svg 所需的核心 Java 类。 已经移植了两个 Java 包,AWT 和 Util。 AWT 类包括 Event 和 Geom 命名...
JSR 303 为实体验证定义了一个元数据模型和API 前端技术选型 JS框架:jQuery 1.8 CSS框架:Twitter Bootstrap 项目所需jar包列表 antlr-2.7.7.jar classmate-1.0.0.jar com.springsource.net.sf.cglib-2.2.0.jar ...
框架核心 1.快速开发(基础功能全部由代码生成器生成) 2.支持前端、后台自定义业务代码扩展,后台提供了大量常用扩展与通用类 3.前端、后台提供了近300个扩展方法与属性,开发人员可在此功能上编写扩展自定义业务代码 4...
如果您喜欢 KeepMoney,请将它介绍给自己的朋友,或者帮助他人安装一个 KeepMoney,又或者写一篇赞扬我们的文章。 如果您愿意支持我们的工作,欢迎您对 KeepMoney 进行捐赠。 版权许可 KeepMoney 基于 GPL 通用...
这是一个早期的。 Procyon 已移至 . 有关最新版本,请参阅 Procyon是一套 Java 元编程工具,专注于代码生成和分析。 它包括以下库: 核心框架 反射框架 表达式框架 编译器工具集(实验性) Procyon 库可从Maven ...
是一系列类和函数的集合,使用核心语言编写,也是C++ISO自身标准的一部分. - 准模板库 (STL). - POSIX系统的C标准库规范. - ISO/IEC JTC1/SC22/WG21 - C++标准委员会. 框架 C++通用框架和库. - 是一系列算法,容器,...