测试执行顺序
重要性:★★★☆☆
如果一个测试类中有多个测试方法,缺省情况下,虽然JUnit会根据一个内在的算法确定这些方法的执行顺序(为了支持“可重复构建”的目标),但是对用户来说,其顺序并不是明显的——测试方法的名称和在测试类中出现的顺序都不是排序的依据。
正常情况下测试类中的每一个测试方法都应该是独立的——它的执行与否以及测试结果都不应该依赖于其他测试方法的预先执行。一个测试方法不应该依赖另一个测试方法为它预设测试条件(例如订单CRUD测试中,查询订单测试不应该依赖于创建订单测试为它先在数据库中创建订单,而应该在自身的setup阶段向数据库中插入测试数据)。
但是有的时候,尤其是在集成测试中,因为要与外部系统如数据库等进行交互,测试类中的每个测试方法在setup阶段都要启动数据库并向其中插入数据,就会导致严重的性能问题。这个时候我们可以接受安排测试方法的执行顺序,例如在订单CRUD测试中,安排创建订单测试先执行,向数据库中插入一到多条订单数据,随后执行查询订单测试和修改订单测试,最后执行删除订单测试。
当需要访问外部基础设施(如数据库、消息中间件等等)或者采用PER_CLASS模式执行测试时,定义测试方法的执行顺序比较有意义。
为了定义测试执行顺序,你需要:
- 用
@TestMethodOrder
注解测试类或测试接口,指定一个MethodOrderer
接口的实现类。 - 如果采用
MethodOrderer
是MethodOrderer.OrderAnnotation
类,在每个要排序的测试方法上添加@Order
注解。@Order
的值越小,方法越先执行。
下面的代码示例根据@Order
注解进行排序:
package yang.yu.tdd.exec_order;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class MethodOrderTest {
@Test
@Order(20)
void last() {
System.out.println("Me last");
}
@Test
@Order(-6)
void first() {
System.out.println("Me first");
}
@Test
@Order(0)
void second() {
System.out.println("Me second");
}
@Test
@Order(2)
void third() {
System.out.println("Me third");
}
}
还可以根据方法名称的字母表顺序进行排序:
package yang.yu.tdd.exec_order;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
@TestMethodOrder(MethodOrderer.Alphanumeric.class)
class AlphanumericOrderTest {
@Test
void last() {
System.out.println("Named last but second in fact");
}
@Test
void first() {
System.out.println("Me first");
}
@Test
void second() {
System.out.println("Named second but third in fact");
}
@Test
void third() {
System.out.println("Named third but last in fact");
}
}
还可以通过将测试类注解为:
@TestMethodOrder(MethodOrderer.Random.class)
来让测试方法伪随机排序执行。不过通常而言这种方式没啥必要。