[Junit] 测试方法执行顺序

Junit 4.11里增长了指定测试方法执行顺序的特性
测试类的执行顺序可经过对测试类添加注解 “@FixMethodOrder(value)” 来指定,其中value 为执行顺序
三种执行顺序可供选择:默认(MethodSorters.DEFAULT),按方法名(MethodSorters.NAME_ASCENDING)和JVM(MethodSorters.JVM)
当没有指定任何顺序时,按默认来执行java

Sorters

1. MethodSorters.DEFAULT数组

默认顺序由方法名hashcode值来决定,若是hash值大小一致,则按名字的字典顺序肯定ide

因为hashcode的生成和操做系统相关(以native修饰),因此对于不一样操做系统,可能会出现不同的执行顺序,在某一操做系统上,屡次执行的顺序不变测试

实现代码:this

复制代码
 /**
     * 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 (推荐) 按方法名称的进行排序,因为是按字符的字典顺序,因此以这种方式指定执行顺序会始终保持一致;spa

不过这种方式须要对测试方法有必定的命名规则,如 测试方法均以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里尤为如此).code

Samples

如下是对Win7 - JDK7 - Junit4.11 的执行结果blog

复制代码
//@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测试方法的执行顺序也不是肯定的