在JUnit中获取当前正在执行的测试的名称

2023/05/09

1. 概述

使用JUnit时,我们可能需要我们的测试能够访问它们的名称。这可能有助于定位错误消息,尤其是对于使用系统生成名称的测试。

在这个简短的教程中,我们将了解如何在JUnit 4JUnit 5中获取当前测试用例的名称。

2. Junit 5

让我们来看两个场景。首先,我们将了解如何访问单个测试的名称。此名称通常是可预测的,因为它可能是方法的名称或@DisplayName注解的值。但是,如果我们使用参数化测试或显示名称生成器,那么我们可能需要知道JUnit提供的名称。

JUnit 5可以将一个TestInfo对象注入到我们的测试方法参数中,通过它我们可以获取当前测试用例的名称。

2.1 单独的测试

private boolean oddCheck(int number) {
    return (number % 2 != 0);
}

@Test
void givenNumbers_whenOddCheck_thenVerify(TestInfo testInfo) {
    System.out.println("displayName = " + testInfo.getDisplayName());
    int number = 5;
    assertTrue(oddCheck(number));
}

这里我们使用了TestInfo接口的getDisplayName()方法来获取测试方法的名称。当我们运行测试时,我们得到测试名称:

displayName = givenNumbers_whenOddCheck_thenVerify(TestInfo)

2.2 参数化测试

让我们用参数化测试来尝试一下。在这里,我们将使用@ParameterizedTest注解的name属性向JUnit描述如何为我们生成测试名称:

private TestInfo testInfo;

@BeforeEach
void init(TestInfo testInfo) {
    this.testInfo = testInfo;
}

@ParameterizedTest(name = "givenNumbers_whenOddCheck_thenVerify {0}")
@ValueSource(ints = {1, 3, 5, -3, 15})
void givenNumbers_whenOddCheck_thenVerify(int number) {
    System.out.println("displayName = " + testInfo.getDisplayName());
    assertTrue(oddCheck(number));
}

我们应该注意,与单独的测试不同,我们不能将TestInfo注入到方法中。这是因为参数化测试的方法参数必须与参数化数据相关。为了解决这个问题,我们需要通过@BeforeEach方法将TestInfo对象保存在测试类的一个字段中

当我们运行测试时,我们得到测试名称:

displayName = givenNumbers_whenOddCheck_thenVerify 15
displayName = givenNumbers_whenOddCheck_thenVerify 5
displayName = givenNumbers_whenOddCheck_thenVerify 1
displayName = givenNumbers_whenOddCheck_thenVerify 3
displayName = givenNumbers_whenOddCheck_thenVerify -3

3. Junit 4

JUnit 4可以在我们的测试中指定一个TestName对象,TestName是一个JUnit Rule。Rule作为JUnit测试执行的一部分执行,使用它可以显示当前正在运行的测试的详细信息。

3.1 单独的测试

让我们考虑一个单独的测试:

@Rule
public TestName name = new TestName();

private static String sortCharacters(String s) {
    char[] charArray = s.toCharArray();
    Arrays.sort(charArray);
    return new String(charArray);
}

@Test
public void givenString_whenSort_thenVerifySortForString() {
    System.out.println("displayName = " + name.getMethodName());
    String s = "abc";
    assertEquals(s, sortCharacters("cba"));
}

如上所示,我们可以使用类TestName的getMethodName()方法来获取测试的名称

让我们运行测试:

displayName = givenString_whenSort_thenVerifySortForString

3.2 参数化测试

现在,让我们使用相同的方法来显示为参数化测试生成的测试名称。首先,我们需要使用特殊的Runner对测试类进行标注:

@RunWith(Parameterized.class)
public class JUnit4ParameterizedTestNameUnitTest {
}

然后,我们可以使用TestName Rule以及用于分配当前测试参数值的字段和构造函数来实现测试:

@RunWith(Parameterized.class)
public class JUnit4ParameterizedTestNameUnitTest {

	private final String input;
	private final String expected;

	@Rule
	public TestName name = new TestName();

	public JUnit4ParameterizedTestNameUnitTest(String input, String expected) {
		this.input = input;
		this.expected = expected;
	}

	private static String sortCharacters(String s) {
		char[] charArray = s.toCharArray();
		Arrays.sort(charArray);
		return new String(charArray);
	}

	@Test
	public void givenString_whenSort_thenVerifySortForString() {
		System.out.println("displayName = " + name.getMethodName());
		assertEquals(expected, sortCharacters(input));
	}
}

在此测试中,我们提供测试数据集合 ,其中包含输入字符串和预期字符串。这是通过suppliedData()方法完成的,并使用@Parameterized.Parameters注解进行标注。此注解还允许我们描述测试名称。

当我们运行测试时,TestName Rule会给出每个测试的名称供我们查看:

displayName = givenString_whenSort_thenVerifySortForString[abc]
displayName = givenString_whenSort_thenVerifySortForString[cba]
displayName = givenString_whenSort_thenVerifySortForString[onm]
displayName = givenString_whenSort_thenVerifySortForString[a]
displayName = givenString_whenSort_thenVerifySortForString[zyx]

4. 总结

在本文中,我们讨论了如何在JUnit 4和JUnit 5中获取当前测试的名称。

我们了解了如何对单个测试和参数化测试执行此操作。

与往常一样,完整的源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章