TimeMeasureUtil:做单次时间测量。
1、为了能确保 startTime 和 endTime 都正确设置,因而采用实例对象来实现。每次测量是都能判断对象是否处在正确状态。
2、该类为工具类,即使测试时产生许多对象实例也对软件无任何影响。
public class TimeMeasureUtil {private long startTime = 0;private long endTime = 0;private TimeMeasureUtil(){}public static TimeMeasureUtil newInstance(){return new TimeMeasureUtil();}public void start(){startTime = System.currentTimeMillis();}public void end(){endTime = System.currentTimeMillis();}public long measure(){// Invalid: Before yif( startTime == 0 ){throw new IllegalStateException( "Must call metod start() first, when call method measure()." );}if( endTime == 0 ){throw new IllegalStateException( "Must call metod end() first, when call method measure()." );}if( startTime > endTime ){throw new IllegalStateException( "Must call metod start() first, when call method end()." );}return endTime - startTime;}}
使用示例:
@Testpublic void testMeasure_ok() {TimeMeasureUtil timeUtil = TimeMeasureUtil.newInstance();timeUtil.start();// 下面这段代码用实际待测方法代替try {Thread.sleep( 1000 );} catch (InterruptedException e) {e.printStackTrace();}timeUtil.end();assertEquals( 1000, timeUtil.measure() );}
TimeMeasureProxy:
1、默认运行20次得平均
2、给定运行次数的平均
缺陷:
1、由于是用反射实现,参数是通过 Object[ ] 来传递。有原始类型(如:byte,int,char...)参数的方法不能测试!只能用 TimeMeasureUtil 来实现测试。
2、如果第一次执行方法后改变了某属性,而该属性改变后又会影响下一次方法的执行(可能会有不同的时间),这样的方法不能测试。可能的改进方式:先“克隆” count 个该对象,然后用这样相同属性的对象来执行方法(每个对象执行一次方法)。因为这样要求,被测试类提供“克隆”方法,“因测试而影响逻辑”不可取,所以没有实现。
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class TimeMeasureProxy {// default measure countprivate int count = 20;private TimeMeasureProxy(){}private TimeMeasureProxy( int count ){this.count = count;}public static TimeMeasureProxy newInstance(){return new TimeMeasureProxy();}public static TimeMeasureProxy newInstance( int count ){return new TimeMeasureProxy( count );}public long avgTime( Object owner, String methodName, Object[] args ){// valid parameters.if( owner == null ){throw new IllegalStateException("owner can't be null.");}if( methodName == null ){throw new IllegalStateException("methodName can't be null.");}Class<?> ownerClass = owner.getClass();Class<?>[] argsClass = null;if( args != null ){argsClass = new Class[ args.length ];for( int i=0 ; i<args.length ; i++ ){argsClass[i] = args[i].getClass();}}Method method;try {method = ownerClass.getMethod( methodName, argsClass );} catch (SecurityException e) {throw new RuntimeException( e );} catch (NoSuchMethodException e) {throw new RuntimeException( e );}return totalTime( owner, method, args)/count;}long totalTime( Object owner, Method method, Object[] args ){long totalTime = 0;try {for( int i=0; i<count ; i++ ){TimeMeasureUtil timeUtil = TimeMeasureUtil.newInstance();timeUtil.start();method.invoke( owner, args );timeUtil.end();totalTime += timeUtil.measure();}} catch (IllegalArgumentException e) {throw new RuntimeException( e );} catch (IllegalAccessException e) {throw new RuntimeException( e );} catch (InvocationTargetException e) {throw new RuntimeException( e );}return totalTime;}}
使用示例:
1、待测试的类
class ForMeasureAvgTime{public void justForTest(){try {Thread.sleep( 335 );} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void justForTestWithParams( Integer age, String name ){try {Thread.sleep( 558 );} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}
2、通过TimeMeasureProxy 来测试
@Test//测量无参数方法&默认次数(20)public void testAvgTime_defaultCount() {ForMeasureAvgTime forMeasure = new ForMeasureAvgTime();TimeMeasureProxy proxy = TimeMeasureProxy.newInstance();long avgTime = proxy.avgTime( forMeasure, "justForTest", null );System.out.println( "avgTime=" + avgTime );assertTrue( (avgTime - 335) < 5 || (335 - avgTime) < 5);}@Test//测量有参数方法&给定次数(10)public void testAvgTime_giveCount() {ForMeasureAvgTime forMeasure = new ForMeasureAvgTime();TimeMeasureProxy proxy = TimeMeasureProxy.newInstance( 10 );long avgTime = proxy.avgTime( forMeasure, "justForTestWithParams", new Object[]{24, "GongQiang"} );System.out.println( "avgTime=" + avgTime );assertTrue( (avgTime - 558) < 5 || (558 - avgTime) < 5);}