写在前面:本文基于Junit3.8.1版本,因为这是我第一次进行源码学习,先从简单的源码开始学起

1. 示例代码

1.1 准备工作

  • 下载Junit3.8.1的JAR包
  • 需要下载junit-3.8.1-sources.jarjunit-3.8.1.jar,前者是源码包,后者是项目中需要使用的Jar包;

1.2 项目中导入Junit相关jar包

  • 使用Eclipse,新建项目test;
  • test右键,选中 properties

1.3 编写示例代码

  • JUnit4之前,JUnit明确要求测试方法名以"test"开头;
  • JUnit 测试类需要继承 "TestCase";
// SampleCalculator.java,需要测试的类
public class SampleCalculator{
// 加法
private int add(int a, int b){
return a + b;
} // 乘法
public int multiply(int a, int b){
return a * b;
} //除法
public double divide(int a, int b){
return a/b;
}
} // 编写测试类,该类需要继承 TestCase
public class TestSample extends TestCase{ private SampleCalculator cal = null; protected void setUp() throws Exception{
super.setUp();
// 每个测试方法执行前,重新new一个对象,避免测试用例之间的依赖
cal = new SampleCalculator():
System.out.println("在每个测试方法执行前执行 ---setUp...");
} // 测试源代码的私有方法
public void testAdd(){
System.out.println("测试方法testAdd...");
try{
// 使用反射,进行私有方法的调用
Class<SampleCalculator> clazz = SampleCalculator.class;
Method method = clazz.getDeclaredMethod("add", new Class[] { Integer.TYPE, Integer.TYPE});
method.setAccessible(true);
Object obj = method.invoke(cal, new Object[]{1, 2});
Assert.assertEquals(3, obj);
}catch(Exception e){
Assert.fail();
}
} // 测试乘法
public void testMultiply(){
System.out.println("测试方法testMultiply...");
Assert.assertEquals.(3, cal.multiply(1, 2));
} // 测试除法
public void testDivice(){
System.out.println("测试方法testDivide...");
Assert.assertEquals(2, cal.divide(1, 0));
} @Override
protected void tearDown() throws Exception{
super.tearDown();
cal = null; // 在每个测试方法执行后,主动销毁对象
System.out.println("在每个测试方法执行后执行--tearDown...\n");
} // main方法调用
public static void main(String[] args){
// 以文字输出的方式,显示运行结果
junit.textui.TestRunner.run(TestSample.class);
// 以图形化界面的方式,显示运行结果
// junit.swingui.TestRunner.run(TestSample.class);
// 以图形化界面的方式,显示运行结果
// junit.awtui.TestRunner.run(TestSample.class);
}
}

备注

  • Failures:表示测试的期待结果与程序运行结果不相符;
  • Errors: 表示测试程序执行过程中,抛出了异常;

2. JUnit运行流程(DEBUG模式运行)

  • JUnit的完整生命周期分为三个阶段:初始化阶段,运行阶段和结果捕捉阶段

2.1 初始化阶段(创建TestCase及TestSuite)

  • 图中红框处,采用了Composite Pattern;while循环第一次,获取TestSample中的方法,

    第二次循环,获取其父类TestCase中的方法: superClass = superClass.getSuperclass();;
// TestSuite.java
public class TestSuite implements Test{ private Vector fTests = new Vector(10);
private String fName; ...(略)
// 将符合条件的测试方法转化为TestCase,并存入到集合中
public void addTestMethod(Method m, Vector names, Class theClass){
String name = m.getName();
if(names.contains(name))
return; // 判断是否是公共方法
if(!isPublicTestMethod(m)){ // 判断是否是测试方法
if(isTestMethod(m))
addTest(warning("Test method isn't public: "+m.getName()));
return;
}
names.addElement(name); // 将testXXX方法转化为 TestCase
addTest(createTest(theClass, name));
} public void addTest(Test test){
fTests.addElement(test);
} // 判断是否是公共方法
public boolean isPublicTestMethod(Method m){
return isTestMethod(m) && Modifier.isPublic(m.getModifiers());
} // 判断是否是测试方法
// 1. 名称以"test"开头
// 2. 无参数,无返回值
public boolean isTestMethod(Method m){
String name = m.getName();
Class[] parameters = m.getParameterTypes();
Class returnType = m.getReturnType();
return parameters.length == 0 && name.startWith("test") && returnType.equals(Void.TYPE);
} // 根据testXXX名称,创建对应的TestCase
static public Test createTest(Class theClass, String name){
Constructor constructor;
try{
constructor = getTestConstructor(theClass);
}catch(NoSuchMethodException e){
...(略)
}
Object test;
try{
if(constructor.getParameterTypes().length == 0){
test = constructor.newInstance(new Object[0]);
if(test instanceof TestCase)
((TestCase)test).setName(name);
}else{
test = constructor.newInstance(new Object[]{name});
}
}catch(Exception e){
...(略)
}
return (Test)test;
}
}

2.2 运行阶段(运行所有TestXXX型的测试方法)

  • 创建TestResult实例;
  • junit.textui.TestRunner的监听器fPrinter加入到result的监听器列表中(观察者模式);
  • 开始计时;
  • run(result)测试运行;
  • 结束计时;
  • 结果输出;

参考资料:

Junit 3.8.1 源码分析(一)的更多相关文章

  1. Junit 3.8.1 源码分析之两个接口

    1. Junit源码文件说明 runner framework:整体框架; extensions:可以对程序进行扩展; textui:JUnit运行时的入口程序以及程序结果的呈现方式; awtui:J ...

  2. JUnit源码分析 - 扩展 - 自定义Rule

    JUnit Rule简述 Rule是JUnit 4.7之后新加入的特性,有点类似于拦截器,可以在测试类或测试方法执行前后添加额外的处理,本质上是对@BeforeClass, @AfterClass, ...

  3. JUnit源码分析 - 扩展 - 自定义RunListener

    RunListener简述 JUnit4中的RunListener类用来监听测试执行的各个阶段,由RunNotifier通知测试去运行.RunListener与RunNotifier之间的协作应用的是 ...

  4. spring源码分析(二)Aop

    创建日期:2016.08.19 修改日期:2016.08.20-2016.08.21 交流QQ:992591601 参考资料:<spring源码深度解析>.<spring技术内幕&g ...

  5. 【JUnit4.10源码分析】5 Statement

    假设要评选JUnit中最最重要的类型.或者说核心,无疑是org.junit.runners.model.Statement.Runner等类型看起来热闹而已. package org.junit.ru ...

  6. Robotium源码分析之Instrumentation进阶-attach

    在分析Robotium的运行原理之前,我们有必要先搞清楚Instrumentation的一些相关知识点,因为Robotium就是基于Instrumentation而开发出来的一套自动化测试框架.鉴于之 ...

  7. Robotium源码分析之Instrumentation进阶

    在分析Robotium的运行原理之前,我们有必要先搞清楚Instrumentation的一些相关知识点,因为Robotium就是基于Instrumentation而开发出来的一套自动化测试框架.鉴于之 ...

  8. Hadoop之HDFS原理及文件上传下载源码分析(上)

    HDFS原理 首先说明下,hadoop的各种搭建方式不再介绍,相信各位玩hadoop的同学随便都能搭出来. 楼主的环境: 操作系统:Ubuntu 15.10 hadoop版本:2.7.3 HA:否(随 ...

  9. MyBatis源码分析之环境准备篇

    前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...

随机推荐

  1. 0066 阿里云大学的几道Java基础测试题

    阿里云大学的几道Java基础测试题: https://edu.aliyun.com/clouder/exam/intro/15 https://edu.aliyun.com/clouder/exam/ ...

  2. 这不是bug,而是语言特性

    分析编程语言缺陷的一种方法是把所有的缺陷归于3类:不该做的做了,该做的没做,该做但做得不合适. 在使用switch case时,如果使用缺省的 fall through,请一定在旁边注释,因为97%的 ...

  3. .NET Standard - 揭秘 .NET Core 和 .NET Standard[转自MSDN]

    作为 .NET 系列的最新成员,.NET Core 和 .NET Standard 的概念及其与 .NET Framework 的区别并不十分明确.在本文中,我将准确介绍每个产品及其适用场景. 在详细 ...

  4. Okra框架(一) 简介

    Okra是一个构建在Netty框架和Disruptor框架之上轻量级JAVA服务器框架. 使用Netty实现高性能,可灵活扩展的网络通信,使用Disruptor实现高吞吐量,低延迟的并发. Okra主 ...

  5. UCOS2系统内核讲述_总体描述

    Ⅰ.写在前面 学习本文之前可以参考我前面基于STM32硬件平台移植UCOS2的几篇文章,我将其汇总在一起: UCOS2_STM32F1移植详细过程(汇总文章) 要想学习,或使用系统配套的资源(如:信号 ...

  6. CI $_GET

    CI默认过滤了$_GET 需要传递get参数时一般直接 /参数一/参数二 详见手册说明:http://codeigniter.org.cn/user_guide/general/controllers ...

  7. 使用asp.net调用谷歌地图api

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> ...

  8. 理财---炒股之kdj

    http://jingyan.baidu.com/article/ac6a9a5ea4e9032b643eac4f.html 28转换: http://zhidao.baidu.com/link?ur ...

  9. linux -- ubuntuserver 安装图形界面

    安装Gnome桌面 1.安装全部桌面环境,其实Ubuntu系列桌面实际上有几种桌面应用程序,包括Ubuntu-desktop.Kubunut-desktop和Xubuntu- desktop. 我们就 ...

  10. SharePoint Survey WebPart 调查 Web部件

    SharePoint Survey WebPart 调查 Web部件 Web部件下载地址 点击此处下载. 安装激活Web部件 过程简单此处省略. 项目描写叙述 调查是SharePoint中协同门户的一 ...