http://jackyrong.iteye.com/blog/2025609
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測試方法的執行順序也不是確定的
---------------------------------------------------------------------
例子:
- import org.junit.FixMethodOrder;
- import org.junit.Test;
- import org.junit.runners.MethodSorters;
- @FixMethodOrder(MethodSorters.NAME_ASCENDING)
- public class OrderedTestCasesExecution {
- @Test
- public void test001First() {
- System.out.println("Executing first test");
- }
- @Test
- public void test002Second() {
- System.out.println("Executing second test");
- }
- @Test
- public void test003Third() {
- System.out.println("Executing third test");
- }
- }
輸出:
Executing first test
Executing second test
Executing third test

