章
目
录
在JUnit 5中,不建议编写顺序测试,但在某些情况下,测试执行顺序可能成为测试应用程序功能(如集成测试)的重要因素。
例如,我们可能需要按以下方式对用户管理模块进行集成测试:创建一个新用户,更新用户,然后删除用户。
1. 测试方法排序
JUnit 5(使用5.8.1版本)支持以下方法在接口MethodOrderer中对测试进行排序:
- MethodName:按字母顺序将测试排序。
- DisplayName:按字母顺序将测试以其显示名称排序。
- OrderAnnotation:根据@Order注释对测试进行排序。具有相同顺序的测试将任意地相邻排列。未排序的测试将出现在末尾。
- Random:以伪随机顺序对测试进行排序。每次执行中的测试随机性可以通过属性junit.jupiter.execution.order.random.seed进行控制。
- Custom:使用提供的排序逻辑对测试进行排序。
- Alphanumeric已被标记为已弃用,将在JUnit 6中删除,因此应避免使用它。
1.1 MethodOrderer.MethodName
根据方法名称对测试进行排序的示例。
@TestMethodOrder(MethodOrderer.MethodName.class)
public class MethodNameOrderedTests
{
@Test
void testE() {
assertTrue(true);
}
@Test
void testA() {
assertTrue(true);
}
@Test
void testD() {
assertTrue(true);
}
@Test
void testC() {
assertTrue(true);
}
@Test
void testB() {
assertTrue(true);
}
}
输出:
testA()
testB()
testC()
testD()
testE()
1.2 MethodOrderer.DisplayName
根据显示名称对测试进行排序的示例。
@TestMethodOrder(MethodOrderer.DisplayName.class)
public class DisplayNameOrderedTests
{
@DisplayName("5")
@Test
void testE() {
assertTrue(true);
}
@DisplayName("3")
@Test
void testA() {
assertTrue(true);
}
@DisplayName("1")
@Test
void testD() {
assertTrue(true);
}
@DisplayName("2")
@Test
void testC() {
assertTrue(true);
}
@DisplayName("4")
@Test
void testB() {
assertTrue(true);
}
}
输出:
1
2
3
4
5
1.3 MethodOrderer.OrderAnnotation
根据@Order注释中对测试进行排序的示例。
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class OrderAnnotationTests {
@Order(5)
@Test
void testE() {
assertTrue(true);
}
@Order(4)
@Test
void testA() {
assertTrue(true);
}
@Order(3)
@Test
void testD() {
assertTrue(true);
}
@Order(2)
@Test
void testC() {
assertTrue(true);
}
@Order(1)
@Test
void testB() {
assertTrue(true);
}
}
输出:
testB()
testC()
testD()
testA()
testE()
1.4 MethodOrderer.Random
以随机顺序对测试进行排序的示例。默认情况下,用于排序方法的随机种子是通过在静态初始化期间生成的System.nanoTime()来生成的。
可以通过提供自定义种子通过属性junit.jupiter.execution.order.random.seed来更改随机性。
junit-platform.properties配置:
junit.jupiter.execution.order.random.seed=9999
@TestMethodOrder(MethodOrderer.Random.class)
public class RandomOrderedTests {
@Test
void testE() {
assertTrue(true);
}
@Test
void testA() {
assertTrue(true);
}
@Test
void testD() {
assertTrue(true);
}
@Test
void testC() {
assertTrue(true);
}
@Test
void testB() {
assertTrue(true);
}
}
默认情况下,测试类的每次执行结果都会不同。但如果我们使用属性文件中的固定种子,测试的顺序将是固定的,不会因不同的执行而改变。
在指定了自定义种子9999后,下面是测试的输出:
//第1次执行
testB()
testC()
testE()
testA()
testD()
//第2次执行
testB()
testC()
testE()
testA()
testD()
1.5 自定义排序
我们实现了自定义排序,这就意味着我们可以通过实现MethodOrderer接口来定义自己的自定义排序。
public class DeprecatedInEndTestOrder implements MethodOrderer {
private Comparator<MethodDescriptor> comparator = Comparator
.comparing(md -> md.getMethod().isAnnotationPresent(Deprecated.class));
@Override
public void orderMethods(MethodOrdererContext context) {
context.getMethodDescriptors().sort(comparator);
}
}
@TestMethodOrder(DeprecatedInEndTestOrder.class)
public class CustomOrderTests {
@Test
@Deprecated
void testC() {
assertTrue(true);
}
@Test
void testA() {
assertTrue(true);
}
@Test
void testD() {
assertTrue(true);
}
@Deprecated
@Test
void testE() {
assertTrue(true);
}
@Test
void testB() {
assertTrue(true);
}
}
注意测试输出。已弃用的测试在最后执行。
testA()
testB()
testD()
testC()
testE()
2. 测试类顺序
重申一点,测试类通常不应依赖于执行顺序,但有时可能需要这样做。
2.1 支持的排序类型
JUnit 5(使用5.8.1版本)支持以下方法在接口ClassOrderer中对测试进行排序。我们可以像上面提到的方法一样使用类顺序。
- ClassName:根据其全限定类名按字母顺序对测试类进行排序。
- DisplayName:根据其显示名称按字母顺序对测试类进行排序。
- OrderAnnotation:根据@Order注释中指定的值对测试类进行排序。
- Random:以伪随机顺序对测试类进行排序。支持使用junit.jupiter.execution.order.random.seed属性设置自定义种子。
要为所有测试类全局设置顺序,请使用junit.jupiter.testclass.order.default配置属性。junit-platform.properties配置:
junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$OrderAnnotation
2.2. 测试类排序示例
嵌套测试类中的测试类排序示例如下所示。
@TestClassOrder(ClassOrderer.OrderAnnotation.class)
class OrderedTestClassesExample {
@Nested
@Order(1)
class SetupTests {
@Test
void test1() {
}
}
@Nested
@Order(2)
class AppFlowTests {
@Test
void test2() {
}
}
}
输出:
SetupTests
- test1()
AppFlowTests
- test2()
3.结论
让我再次强调,强制执行测试的顺序是不推荐的,应该避免。但是,如果您遇到此类要求,则可以使用上述解释的技巧来排序测试类和测试方法。
如果测试顺序对您的情况非常重要,我建议您使用@Order注释与ClassOrderer.OrderAnnotation和MethodOrderer.OrderAnnotation来完全控制测试的顺序。