1.概述

在本文中,我们将看一下JUnit 5中引入的*@RepeatedTest*注释。

它为我们提供了一种强大的方式来编写我们想要重复多次的任何测试。

如果您想了解有关JUnit 5的更多信息,请查看我们的介绍文章

2. Maven依赖关系和设置

首先需要注意的是JUnit 5需要Java 8以上。 让我们来看看Maven依赖:

<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-engine</artifactId>
  <version>5.1.0</version>
  <scope>test</scope>
</dependency>

3.一个简单的@RepeatedTest示例

创建重复测试很简单, 我们只需在测试方法的顶部添加*@RepeatedTest*注释:

@RepeatedTest(3)
void repeatedTest(TestInfo testInfo) {
  System.out.println("重复执行测试");
  assertEquals(2, Math.addExact(1, 1), "1 + 1 =  2");
}

在上面的代码中,我们使用*@RepeatedTest代替标准@Test*注释。

上面的测试将执行三次,就好像相同的测试被写三次一样。

控制台的输出如下:

重复执行测试
重复执行测试
重复执行测试

而在IDE的JUnit选项卡中的结果,会向下面这样显示:

repetition 1 of 3
repetition 2 of 3
repetition 3 of 3

4. @ RepeatedTest的生命周期支持

@RepeatedTest的每次执行都具有完整JUnit测试生命周期支持,和*@Test*是一样的。

这意味着,在*@RepeatedTest每次执行期间,将调用@BeforeEach@AfterEach*方法。

为了演示这一点,只需在测试类中添加一些方法:

@BeforeEach
void beforeEachTest() {
  System.out.println("=====================");
  System.out.println("Before Each Test");
}

@AfterEach
void afterEachTest() {
  System.out.println("After Each Test");
  System.out.println("=====================");
}

运行上面的测试,控制台将会输出:

=====================
Before Each Test
重复执行测试
After Each Test
=====================
=====================
Before Each Test
重复执行测试
After Each Test
=====================
=====================
Before Each Test
重复执行测试
After Each Test
=====================

每次执行都会调用@BeforeEach和@AfterEach方法

5. 设置测试的名称

在第一个示例中,我们观察到测试报告的输出不包含任何标识符。我们可以使用name属性进行设置:

@RepeatedTest(value = 3, name = RepeatedTest.LONG_DISPLAY_NAME)
void repeatedTestWithLongName() {
  System.out.println("显示完整的的方法名");

  assertEquals(2, Math.addExact(1, 1), "1 + 1 = 2");
}

在IDE的JUnit选项卡将包含方法名称和重复索引:

repeatedTestWithLongName() :: repetition 1 of 3
repeatedTestWithLongName() :: repetition 2 of 3
repeatedTestWithLongName() :: repetition 3 of 3

另一种选择是使用RepeatedTest.SHORT_DISPLAY_NAME,它将忽略方法名:

@RepeatedTest(value = 3, name = RepeatedTest.SHORT_DISPLAY_NAME)
void repeatedTestWithShortName() {
  System.out.println("忽略方法名");
  assertEquals(2, Math.addExact(1, 1), "1 + 1 = 2");
}

在IDE的JUnit选项卡中显示如下:

repetition 1 of 3
repetition 2 of 3
repetition 3 of 3

我们还可以自定的名字

@RepeatedTest(value = 3, name = "自定的测试名字 {currentRepetition}/{totalRepetitions}")
void repeatedTestWithCustomDisplayName(TestInfo testInfo) {
  assertEquals(2, Math.addExact(1, 1), "1 + 1 = 2");
}

上面代码中*{currentRepetition}{totalRepetitions}*表示对于当前重复和重复的总数中的占位符。

这些值由JUnit在运行时自动提供,无需其他配置。

自定的测试名字 1/3
自定的测试名字 2/3
自定的测试名字 3/3

6. 访问RepetitionInfo

除了name属性之外,JUnit还提供对测试代码中重复元数据的访问。

我们可以通过向我们的测试方法添加RepetitionInfo参数来实现的:

@RepeatedTest(3)
void repeatedTestWithRepetitionInfo(RepetitionInfo repetitionInfo) {
  System.out.println("当前的次数 #" + repetitionInfo.getCurrentRepetition());

  assertEquals(3, repetitionInfo.getTotalRepetitions());
}

控制的输出(把before和after的输出去掉了):

当前的次数 #1
当前的次数 #2
当前的次数 #3

RepetitionInfo是通过RepetitionInfoParameterResolver提供的,只能在*@RepeatedTest*上下文中使用。

7. 结论

在本文程中,我们探索了JUnit提供的*@RepeatedTest*注释。

最后,往常一样,代码可以在Github上找到。