JUnit5:指定多个@Nested的执行顺序类

JUnit5: Specify order of execution of multiple @Nested classes

Junit5 是否对同一父级中定义的 @Nested 类 的执行顺序提供任何保证?通过我做的一个简单的例子,我注意到测试是按照声明的相反顺序执行的,但是这种行为既没有记录(或者是?)也不符合默认情况下 @Test 注释方法的排序方式。

这也很烦人,因为显然我宁愿有一个非反向顺序,如果不是一种类似于 @TestMethodOrder.

的配置方式的话
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

class NestedOrderTest {
    @Nested
    class NestedTest1 {
        @Test
        void testSuccess1() {
            System.out.println(1);
        }
    }

    @Nested
    class NestedTest2 {
        @Test
        void testSuccess2() {
            System.out.println(2);
        }
    }

    @Nested
    class NestedTest3 {
        @Test
        void testSuccess3() {
            System.out.println(3);
        }
    }
}

输出:

3
2
1

默认情况下,单元测试库不会尝试按照源文件中出现的顺序执行测试。
JUnit 5 和 JUnit 4 一样以这种方式工作。为什么 ?因为如果顺序很重要,这意味着一些测试在它们之间是耦合的,这对于单元测试来说是不可取的(重点是我的):

2.9. Test Execution Order

By default, test methods will be ordered using an algorithm that is deterministic but intentionally nonobvious. This ensures that subsequent runs of a test suite execute test methods in the same order, thereby allowing for repeatable builds.

因此,预计 JUnit 5 引入的 @Nested 功能遵循相同的默认方法。

但对于集成测试,测试方法的顺序可能很重要,因为在执行的测试方法之间不一定会清除状态。
因此,在 JUnit 5 中,您同样可以通过使用 @TestMethodOrder(OrderAnnotation.class) 注释测试 class 并为顺序重要的方法指定顺序 @Order(numericOrderValue) 来设置执行顺序。

但是 @Order 旨在装饰要测试的方法,而不是您想要的测试 class 本身:

@API(status = EXPERIMENTAL, since = "5.4")
@Target({ ElementType.FIELD, ElementType.METHOD })
public @interface Order {...}

您还可以注意到这是一项实验性功能。

因此,您可以在此处订购的唯一一件事是同一 @Nested 范围内的测试方法,例如:

@Nested
class NestedTest1 {

    @Order(3)
    @Test
    void success3() {
        System.out.println(3);
    }

    @Order(2)
    @Test
    void success2() {
        System.out.println(2);
    }

    @Order(1)
    @Test
    void success1() {
        System.out.println(1);
    }
}

输出:

1

2

3

顺便说一下,指定 @TestMethodOrder(OrderAnnotation.class) 看起来不需要(至少在我测试的 5.4.0 版本中)。

已在 Junit 5.8 中添加 @Nested class 排序功能。至此,平台给了用户可能需要的一切保障。

import org.junit.jupiter.api.ClassOrderer;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestClassOrder;

@TestClassOrder(ClassOrderer.OrderAnnotation.class)
class OrderedNestedTestClassesDemo {

    @Nested
    @Order(1)
    class PrimaryTests {

        @Test
        void test1() {
        }
    }

    @Nested
    @Order(2)
    class SecondaryTests {

        @Test
        void test2() {
        }
    }
}