一个演示Junit4实现原理的ut

12 篇文章 0 订阅
12 篇文章 0 订阅

文|码术张

本文旨在说明Junit4源代码的设计思想。
说明方式上,使用的是自己的一个创新的想法:
用一个ut来说明。

代码如下;

package test;

import org.junit.Test;

public class IpTest {

    @Test
    public void should_True() throws Exception{
        MyNotifier notifier = new MyNotifier();
        MyResult result = new MyResult();
        notifier.addListener(result.createListener());
        notifier.addListener(new Detail());
        MyDescription description = MyDescription.createMyDescriptionn("IpTest", "");

        notifier.fireTestRunStarted(description);

            MyDescription descriptionForA = MyDescription.createMyDescriptionn("IpTest", "methodA");

            notifier.fireTestStarted(descriptionForA);
            System.out.println("Hi..., I am method A");
            notifier.fireTestFinished(descriptionForA);

            MyDescription descriptionForB = MyDescription.createMyDescriptionn("IpTest", "methodB");
            notifier.fireTestStarted(descriptionForB);
            System.out.println("Hi..., I am method B");
            notifier.fireTestFinished(descriptionForB);

        notifier.fireTestRunFinished(result);

    }

}

类图:
类图

交互图:
交互图
在class IpTest中,有一个should_True方法。
这个方法的实现,即演示了Junit4的实现原理。
MyNotifier、MyResult、MyDescription,
对就Junit源码中类Notifier、Result、Description。

程序运行时,首先发布一个事件fireTestRunStarted;
运行结束时,发布一个一个事件fireTestRunFinished。

类的每一个方法运行时,首先发布一个事件fireTestStarted;
类的每一个方法结束时,会发现一个事件fireTestFinished。

Listener收到事件后,会做一些操作。
这些操作的结果会在程序结时,打印出来:
运行结果
在Junit源代码中,每个方法会有一个用职责链模式构建一个Statement类的对象。
一个方法的执行,即是依次执行这个链表上的语句。
这点没在本文中体现。

本文所用的其他代码如下:

package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


public class MyNotifier {
    private final List<MyRunListener> fListeners =
    Collections.synchronizedList(new ArrayList<MyRunListener>());
	
	
	public void addListener(MyRunListener listener) {
        fListeners.add(listener);
    }
	
	
	public void fireTestRunStarted(final MyDescription description) throws Exception {
		for (MyRunListener each : fListeners) {
				each.testRunStarted(description);
		}
			
	}
	
	public void fireTestRunFinished(final MyResult result) throws Exception{
		for (MyRunListener each : fListeners) {
				each.testRunFinished(result);
		}
		
    }
	
	
	public void fireTestStarted(final MyDescription description) throws Exception{
		for (MyRunListener each : fListeners) {
				each.testStarted(description);
		}		
		
	}
	
	public void fireTestFinished(final MyDescription description)	throws Exception{
		for (MyRunListener each : fListeners) {
				each.testFinished(description);
		}	
		
	}
}

package test;

import java.util.concurrent.atomic.AtomicInteger;


public class MyResult {

    private AtomicInteger fCount = new AtomicInteger();
	private long fRunTime = 0;
	private long fStartTime;


	public int getRunCount() {
		return fCount.get();
	}
	

    public long getRunTime() {
        return fRunTime;
    }	
	


    private class Listener extends MyRunListener {
        @Override
        public void testRunStarted(MyDescription description) throws Exception {
            fStartTime = System.currentTimeMillis();
        }

        @Override
        public void testRunFinished(MyResult result) throws Exception {
            long endTime = System.currentTimeMillis();
            fRunTime += endTime - fStartTime;
        }

        @Override
        public void testFinished(MyDescription description) throws Exception {
            fCount.getAndIncrement();
        }

    }	
	
	
	public MyRunListener createListener() {
        return new Listener();
    }
}

package test;

import org.junit.runner.notification.Failure;

public class Detail  extends MyRunListener {
    public void testRunStarted(MyDescription description) throws Exception {
        println("==>JUnit4 started with description: \n" + description);
        println();
        
      }
    
      public void testRunFinished(MyResult result) throws Exception {
        println("==>JUnit4 finished with result: \n" + describe(result));
      }
    
      public void testStarted(MyDescription description) throws Exception {
        println("==>Test method started with description: " + description);
      }
    
      public void testFinished(MyDescription description) throws Exception {
        println("==>Test method finished with description: " + description);
        println();
      }
    
      public void testFailure(Failure failure) throws Exception {
        println("==>Test method failed with failure: " + failure);
      }
    
      public void testAssumptionFailure(Failure failure) {
        println("==>Test method assumption failed with failure: " + failure);
      }
    
      public void testIgnored(MyDescription description) throws Exception {
        println("==>Test method ignored with description: " + description);
        println();
      }
    
      private String describe(MyResult result) {
        StringBuilder builder = new StringBuilder();
        builder.append("\tRunCount: " + result.getRunCount())
            .append("\n");
        ;
        builder.append("\tRunTime: " + result.getRunTime())
            .append("\n");

        ;
        return builder.toString();
      }
    
      private void println() {
        System.out.println();
      }
    
      private void println(String content) {
        System.out.println(content);
      }
}

package test;

public class MyDescription {
    private  String fclassName;
    private  String fMethodName;

    public String getMethodName() {
        return fMethodName;
    }

    public String getClassName() {
        return fclassName;
    }

    @Override
    public String toString() {
        return getDisplayName();
    }

    /**
     * @return a user-understandable label
     */
    public String getDisplayName() {
        return formatDisplayName(fMethodName, fclassName);
    }

    private MyDescription(String className, String methodName) {
        fclassName = className;
        fMethodName = methodName;
    }

    public static MyDescription createMyDescriptionn(String className, String methodName) {
        return new MyDescription( className,  methodName);
    }

    private static String formatDisplayName(String name, String className) {
        return String.format("%s(%s)", name, className);
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值