JUnit 5 测试执行顺序详解

后端 潘老师 6个月前 (10-24) 130 ℃ (0) 扫码查看

在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来完全控制测试的顺序。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/10310.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】