异乡客

我一生戎马刀上飘 见过英雄弯下小蛮腰 飞檐走壁能飞多高 我坐船练习水上漂

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
参考:http://www.cnblogs.com/lukehuang/archive/2013/08/27.html 

Brief 
Junit 4.11里增加了指定测试方法执行顺序的特性 

测试类的执行顺序可通过对测试类添加注解 “@FixMethodOrder(value)” 来指定,其中value 为执行顺序 

三种执行顺序可供选择:默认(MethodSorters.DEFAULT),按方法名(MethodSorters.NAME_ASCENDING)和JVM(MethodSorters.JVM) 

当没有指定任何顺序时,按默认来执行 
Sorters 
1. MethodSorters.DEFAULT 
默认顺序由方法名hashcode值来决定,如果hash值大小一致,则按名字的字典顺序确定 
由于hashcode的生成和操作系统相关(以native修饰),所以对于不同操作系统,可能会出现不一样的执行顺序,在某一操作系统上,多次执行的顺序不变 
实现代码: 

复制代码 
/** 
     * DEFAULT sort order 
     */ 
    public static Comparator<Method> DEFAULT = new Comparator<Method>() { 
        public int compare(Method m1, Method m2) { 
            int i1 = m1.getName().hashCode(); 
            int i2 = m2.getName().hashCode(); 
            if (i1 != i2) { 
                return i1 < i2 ? -1 : 1; 
            } 
            return NAME_ASCENDING.compare(m1, m2); 
        } 
    }; 
复制代码 
2. MethodSorters.NAME_ASCENDING (推荐) 
按方法名称的进行排序,由于是按字符的字典顺序,所以以这种方式指定执行顺序会始终保持一致; 
不过这种方式需要对测试方法有一定的命名规则,如 测试方法均以testNNN开头(NNN表示测试方法序列号 001-999) 

复制代码 
  /** 
     * Method name ascending lexicographic sort order, with {@link Method#toString()} as a tiebreaker 
     */ 
    public static Comparator<Method> NAME_ASCENDING = new Comparator<Method>() { 
        public int compare(Method m1, Method m2) { 
            final int comparison = m1.getName().compareTo(m2.getName()); 
            if (comparison != 0) { 
                return comparison; 
            } 
            return m1.toString().compareTo(m2.toString()); 
        } 
    }; 
复制代码 
3. MethodSorters.JVM 
按JVM返回的方法名的顺序执行,此种方式下测试方法的执行顺序是不可预测的,即每次运行的顺序可能都不一样(JDK7里尤其如此). 
Samples 
以下是对Win7 - JDK7 - Junit4.11 的执行结果 

复制代码 
//@FixMethodOrder(MethodSorters.DEFAULT) 
//@FixMethodOrder(MethodSorters.NAME_ASCENDING) 
@FixMethodOrder(MethodSorters.JVM) 
public class TestJunitOrder { 

    @Test    
    public void test003Third() {        
        
        System.out.println("test003Third"); 
    } 
    
    @Test    
    public void test001First() {        
        
        System.out.println("test001First"); 
    } 
    
    @Test    
    public void test002Second() {        
        
        System.out.println("test002Second"); 
    } 

复制代码 
1. DEFAULT 
结果始终为: 
test002Second 
test001First 
test003Third 

2. NAME_ASCENDING 
结果始终为: 
test001First 
test002Second 
test003Third 

3. JVM 
多数情况下 结果为: 
test002Second 
test001First 
test003Third 
偶尔出现: 
test001First 
test003Third 
test002Second 
Dig more .. 
实际上 Junit里是通过反射机制得到某个Junit里的所有测试方法,并生成一个方法的数组,然后依次执行数组里的这些测试方法; 
而当用annotation指定了执行顺序,Junit在得到测试方法的数组后,会根据指定的顺序对数组里的方法进行排序;

复制代码 
  public static Method[] getDeclaredMethods(Class<?> clazz) { 
        Comparator<Method> comparator = getSorter(clazz.getAnnotation(FixMethodOrder.class));//获取测试类指定的执行顺序 

        Method[] methods = clazz.getDeclaredMethods(); 
        if (comparator != null) { 
            Arrays.sort(methods, comparator);//根据指定顺序排序 
        } 

        return methods; 
    } 
复制代码 
三种执行顺序的定义如下: 

复制代码 
/** 
     * Sorts the test methods by the method name, in lexicographic order, 
     * with {@link Method#toString()} used as a tiebreaker 
     */ 
    NAME_ASCENDING(MethodSorter.NAME_ASCENDING), 

    /** 
     * Leaves the test methods in the order returned by the JVM. 
     * Note that the order from the JVM may vary from run to run 
     */ 
    JVM(null), 

    /** 
     * Sorts the test methods in a deterministic, but not predictable, order 
     */ 
    DEFAULT(MethodSorter.DEFAULT); 
复制代码 
由上可以看出 当设置为MethodSorters.JVM时,其并没有提供一个Comparator的实现,所以执行方法的顺序实际上就是 clazz.getDeclaredMethods();得到的数组里方法的顺序,而由于java里对getDeclaredMethods返回的方法没有指定任何顺序,所以最终导致Junit测试方法的执行顺序也不是确定的 


--------------------------------------------------------------------- 
例子: 
 
Java代码  收藏代码
  1. import org.junit.FixMethodOrder;  
  2. import org.junit.Test;  
  3. import org.junit.runners.MethodSorters;  
  4.   
  5. @FixMethodOrder(MethodSorters.NAME_ASCENDING)  
  6. public class OrderedTestCasesExecution {  
  7.     @Test  
  8.     public void test001First() {  
  9.         System.out.println("Executing first test");  
  10.           
  11.     }  
  12.   
  13.     @Test  
  14.     public void test002Second() {  
  15.       
  16.         System.out.println("Executing second test");  
  17.     }  
  18.   
  19.     @Test  
  20.     public void test003Third() {  
  21.         System.out.println("Executing third test");  
  22.     }  
  23. }  


输出: 
  Executing first test 
Executing second test 
Executing third test 
posted on 2015-09-21 17:47  cvv54  阅读(191)  评论(0编辑  收藏  举报