Junit 3.8.1 源码分析之两个接口

Posted 思考与践行

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Junit 3.8.1 源码分析之两个接口相关的知识,希望对你有一定的参考价值。

1. Junit源码文件说明

  • runner
  • framework:整体框架;
  • extensions:可以对程序进行扩展;
  • textui:JUnit运行时的入口程序以及程序结果的呈现方式;
  • awtui:JUnit运行时的入口程序以及程序结果的呈现方式;
  • swingui:JUnit运行时的入口程序以及程序结果的呈现方式;

2. Junit 的两个重要接口(TestTestListener)

2.1 Test接口

// Junit源码
// Test.java
public interface Test{
    // 统计测试方法
    public abstract int countTestCases();

    // 对方法进行测试,以及汇总测试结果
    public abstract void run(TestResult result);
}

// TestCase.java(单个测试方法)
// 继承Assert类,实现Test类
public abstract class TestCase extends Assert implements Test{
    ...(略)
   
    public int countTestCases(){
        return 1;
    }

    public TestResult run(){
        TestResult result = createResult();
        run(result);
        return result;
    }

    // 实现接口的方法
    public void run(TestResult result){
        result.run(this);
    }
 

    public void runBare() throws Throwable{
        setUp();
        try{
            runTest();
        }finally{
            tearDown();
        }
    }

    ...(略)
}

//TestSuite.java(一组测试方法)
public class TestSuite implements Test{
    private Vector fTests = new Vector(10);
    private String fName;

    public Enumeration tests(){
        return fTests.elements();
    }

    public int countTestCases(){
        int count = 0;
        for(Enumeration e = tests(); e.hasMoreElements(); ){
            Test test = (Test)e.nextElement();
            count = count + test.countTestCases();
        }
        return count;
    }

    public void run(TestResult result){
        for(Enumeration e = tests(); e.hasMoreElements(); ){
            if(result.shouldStop())
                break;
            Test test = (Test)e.nextElement();
            runTest(test, result);
        }
    }

    public void runTest(Test test, TestResult result){
        test.run(result);
    }
}

//Assert类,对测试方法结果的断言
public class Assert{
    // 构造方法
    protected Assert(){
    }

    // 静态方法
    static public void assertTrue(String message, boolean condition){
        if(!condition)
            fail(message);
    }
    static public void assertFalse(String message, boolean condition){
        assertTrue(message, !condition);
    }
    static public void fail(String message){
        throw new AssertionFailedError(message);
    }

    static public void assertEquals(String message, Object expected, Object actual){
        if(expected == null && actual == null)
            return;
        if(expected != null && expected.equals(actual))
            return;
        failNotEquals(message, expected, actual);
    }

    ...(略)

    static private void failNotEquals(String message, Object expected, Object actual){
        fail(format(message, expected, actual));
    }

    static String format(String message, Object expected, Object actual){
        String formatted = "";
        if(message != null)
            formatted= message + " ";
        return formatted+"expected:<"+expected+"> but was:<"+actual+">";
    }
}

// TestResult 类,测试结果类
public class TestResult extends Object {
    protected Vector fFailures;
    protected Vector fErrors;
    protected Vector fListeners;
    protected int fRunTests;
    private boolean fStop;

    public TestResult(){
        fFailures = new Vector();
        fErrors = new Vector();
        fListeners = new Vector();
        fRunTests = 0;
        fStop = false;
    }

    ...(略)
    //运行测试方法
    protected void run(final TestCase test){
        startTest(test);
        Protectable p = new Protectable(){
            public void protect() throws Throwable{
                test.runBare();
            }
        };
        runProtected(test, p);
        endTest(test);
    }

    public void startTest(Test test){
        final int count = test.countTestCases();
        synchronized(this){
            fRunTests+=count;
        }
        for(Enumeration e = cloneListeners().elements(); e.hasMoreElements(); ){
            ((TestListener)e.nextElement()).startTest(test);
        }
    }

    public void runProtected(final Test test, Protectable p){
        try{
            p.protect();
        }
        catch(AssertionFailedError e){
            addFailure(test, e);
        }
        catch(ThreadDeath e){
            throw e;
        }
        catch(Throwable e){
            addError(test, e);
        }
    }

    public void endTest(Test test){
        for(Enumeration e = cloneListeners().elements(); e.hasMoreElements(); ){
            ((TestListener)e.nextElement()).endTest(test);
        }
    }
}

2.2 TestListener接口

// TestListener.java
public interface TestListener{
    public void addError(Test test, Throwable t);
    public void addFailure(Test test, AssertionFailedError t);
    public void endTest(Test test);
    public void startTest(Test test);
}

// 负责结果打印
// ResultPrinter.java
public class ResultPrinter implements TestListener{
    //打印"E"
    public void addError(Test test, Throwable t){
        getWriter().print("E");
    }
    //打印"F"
    public void addFailure(Test test, AssertionFailedError t){
        getWriter().print("F");
    }
    public void endTest(Test test){    
    }
    public void startTest(Test test){
        getWriter().print(".");
        if(fColumn++ >= 40){
            getWriter().println();
            fColumn = 0;
        }
    }
    ...(略)
}

// 所有TestRunListener的基类
// BaseTestRunner.java
public abstract class BaseTestRunner implements TestListener{
    public synchronized void startTest(Test test){
        testStarted(test.toString());
    }
    public synchronized void endTest(Test test){
        testEnded(test.toString());
    }
    public synchronized void addError(final Test test, final Throwable t){
        testFailed(TestRunListener.STATUS_ERROR, test, t);
    }
    public synchronized void addFailure(final Test test, final AssertionFailedError t){
        testFailed(TestRunListener.STATUS_FAILURE, test, t);
    }

    // TestRunListener需要实现
    public abstract void testStarted(String testName);
    public abstract void testEnded(String testName);
    public abstract void testFailed(int status, Test test, Throwable t);
}

参考资料:

以上是关于Junit 3.8.1 源码分析之两个接口的主要内容,如果未能解决你的问题,请参考以下文章

以太坊源码分析-同步之Syncing接口

Spring 源码分析之AbstractApplicationContext源码分析

源码分析之委派模式与适配器模式

mybatis源码分析之04Mapper接口的动态代理

Android 插件化VirtualApp 源码分析 ( 目前的 API 现状 | 安装应用源码分析 | 安装按钮执行的操作 | 返回到 HomeActivity 执行的操作 )(代码片段

Android 跨进程通信-AIDL中的代理模式之源码分析