java 单元测试类指定方法执行顺序

时间:2021-02-20 19:33:20

说明: Junit4.11版本及以后才支持,建议升级到最新版本.

按照设计原则,JUnit是不指定测试方法调用执行顺序的。
目前为止,这些方法只是简单地按照反射(reflection) API返回的顺序执行。
但是,使用JVM默认提供的排序是很不明智的,因为Java平台没有指定任何有规律的顺序,
而事实上JDK 7可能会返回一个随机的顺序。
当然,精心编写的测试代码之间并不需要假定任何执行顺序,但有时候,但在某些平台上一个可预测的失败总比随机的失败要好。

从4.11版本开始,JUnit将默认使用一个确定的,但不可预测的顺序( MethodSorters.DEFAULT )。
要改变测试执行的顺序只需要在测试类(class)上使用 @FixMethodOrder 注解,并指定一个可用的MethodSorter即可:

@FixMethodOrder(MethodSorters.JVM) : 保留测试方法的执行顺序为JVM返回的顺序。每次测试的执行顺序有可能会所不同。

@FixMethodOrder(MethodSorters.NAME_ASCENDING) :根据测试方法的方法名排序,按照词典排序规则(ASC,从小到大,递增)。



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

Java代码  java 单元测试类指定方法执行顺序
  1. /** 
  2.      * DEFAULT sort order 
  3.      */  
  4.     public static Comparator<Method> DEFAULT = new Comparator<Method>() {  
  5.         public int compare(Method m1, Method m2) {  
  6.             int i1 = m1.getName().hashCode();  
  7.             int i2 = m2.getName().hashCode();  
  8.             if (i1 != i2) {  
  9.                 return i1 < i2 ? -1 : 1;  
  10.             }  
  11.             return NAME_ASCENDING.compare(m1, m2);  
  12.         }  
  13.     };   

 2. MethodSorters.NAME_ASCENDING (推荐) 
按方法名称的进行排序,由于是按字符的字典顺序,所以以这种方式指定执行顺序会始终保持一致; 
不过这种方式需要对测试方法有一定的命名规则,如 测试方法均以testNNN开头(NNN表示测试方法序列号 001-999)

Java代码  java 单元测试类指定方法执行顺序
  1. /** 
  2.      * Method name ascending lexicographic sort order, with {@link Method#toString()} as a tiebreaker 
  3.      */  
  4.     public static Comparator<Method> NAME_ASCENDING = new Comparator<Method>() {  
  5.         public int compare(Method m1, Method m2) {  
  6.             final int comparison = m1.getName().compareTo(m2.getName());  
  7.             if (comparison != 0) {  
  8.                 return comparison;  
  9.             }  
  10.             return m1.toString().compareTo(m2.toString());  
  11.         }  
  12.     };   

 

3. MethodSorters.JVM 
按JVM返回的方法名的顺序执行,此种方式下测试方法的执行顺序是不可预测的,即每次运行的顺序可能都不一样(JDK7里尤其如此). 
Samples 
以下是对Win7 - JDK7 - Junit4.11 的执行结果

Java代码  java 单元测试类指定方法执行顺序
  1. //@FixMethodOrder(MethodSorters.DEFAULT)  
  2. //@FixMethodOrder(MethodSorters.NAME_ASCENDING)  
  3. @FixMethodOrder(MethodSorters.JVM)  
  4. public class TestJunitOrder {  
  5.   
  6.     @Test     
  7.     public void test003Third() {         
  8.          
  9.         System.out.println("test003Third");  
  10.     }  
  11.      
  12.     @Test     
  13.     public void test001First() {         
  14.          
  15.         System.out.println("test001First");  
  16.     }  
  17.      
  18.     @Test     
  19.     public void test002Second() {         
  20.          
  21.         System.out.println("test002Second");  
  22.     }  
  23. }   

 实际上 Junit里是通过反射机制得到某个Junit里的所有测试方法,并生成一个方法的数组,然后依次执行数组里的这些测试方法; 
而当用annotation指定了执行顺序,Junit在得到测试方法的数组后,会根据指定的顺序对数组里的方法进行排序;

Java代码  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.     }