JUnit Custom Display Name Generator API – JUnit自定义显示名称生成器API

最后修改: 2019年 7月 13日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

JUnit 5 has good support for customizing test class and test method names. In this quick tutorial, we’ll see how we can use JUnit 5 custom display name generators via the @DisplayNameGeneration annotation.

JUnit 5对自定义测试类和测试方法名称有很好的支持。在这个快速教程中,我们将看到如何通过@DisplayNameGeneration注解使用JUnit 5自定义显示名称生成器。

2. Display Name Generation

2.显示名称的生成

We can configure custom display name generators via the @DisplayNameGeneration annotation. However, it’s good to be aware that the @DisplayName annotation always takes precedence over any display name generator.

我们可以通过@DisplayNameGeneration注解来配置自定义显示名称生成器。然而,最好注意的是,@DisplayName 注解总是优先于任何显示名称生成器。

To start with, JUnit 5 provides a DisplayNameGenerator.ReplaceUnderscores class that replaces any underscores in names with spaces. Let’s take a look at an example:

首先,JUnit 5提供了一个DisplayNameGenerator.ReplaceUnderscores类,它将名称中的任何下划线替换为空格。让我们来看看一个例子。

@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class ReplaceUnderscoresGeneratorUnitTest {

    @Nested
    class when_doing_something {

        @Test
        void then_something_should_happen() {
        }

        @Test
        @DisplayName("@DisplayName takes precedence over generation")
        void override_generator() {
        }
    }
}

Now, when we run the test we can see the display name generation made the test output more readable:

现在,当我们运行测试时,我们可以看到显示名称的生成使测试的输出更加可读。

└─ ReplaceUnderscoresGeneratorUnitTest ✓
   └─ when doing something ✓
      ├─ then something should happen() ✓
      └─ @DisplayName takes precedence over generation ✓

3. Custom Display Name Generator

3.自定义显示名称生成器

In order to write a custom display name generator, we have to write a class that implements the methods in the DisplayNameGenerator interface. The interface has methods for generating the name for a class, a nested class, and a method.

为了编写一个自定义显示名称生成器,我们必须编写一个实现DisplayNameGenerator接口中方法的类。该接口有为一个类、一个嵌套类和一个方法生成名称的方法。

3.1. Camel Case Replacement

3.1.骆驼壳更换

Let’s start with a simple display name generator that replaces camel case names with readable sentences. To begin with, we can extend the DisplayNameGenerator.Standard class:

让我们从一个简单的显示名称生成器开始,用可读的句子替换骆驼字母的名称。首先,我们可以扩展DisplayNameGenerator.Standard

    static class ReplaceCamelCase extends DisplayNameGenerator.Standard {
        @Override
        public String generateDisplayNameForClass(Class<?> testClass) {
            return replaceCamelCase(super.generateDisplayNameForClass(testClass));
        }

        @Override
        public String generateDisplayNameForNestedClass(Class<?> nestedClass) {
            return replaceCamelCase(super.generateDisplayNameForNestedClass(nestedClass));
        }

        @Override
        public String generateDisplayNameForMethod(Class<?> testClass, Method testMethod) {
            return this.replaceCamelCase(testMethod.getName()) + 
              DisplayNameGenerator.parameterTypesAsString(testMethod);
        }

        String replaceCamelCase(String camelCase) {
            StringBuilder result = new StringBuilder();
            result.append(camelCase.charAt(0));
            for (int i=1; i<camelCase.length(); i++) {
                if (Character.isUpperCase(camelCase.charAt(i))) {
                    result.append(' ');
                    result.append(Character.toLowerCase(camelCase.charAt(i)));
                } else {
                    result.append(camelCase.charAt(i));
                }
            }
            return result.toString();
        }
    }

In the above example, we can see the methods that generate different parts of the display name.

在上面的例子中,我们可以看到生成显示名称的不同部分的方法。

Let’s write a test for our generator:

让我们为我们的发电机写一个测试。

@DisplayNameGeneration(DisplayNameGeneratorUnitTest.ReplaceCamelCase.class)
class DisplayNameGeneratorUnitTest {

    @Test
    void camelCaseName() {
    }
}

Next, when running the test, we can see that the camel case names have been replaced with readable sentences:

接下来,在运行测试时,我们可以看到骆驼的名字已经被替换成可读的句子

└─ Display name generator unit test ✓
   └─ camel case name() ✓

3.2. Indicative Sentences

3.2.指示性句子

So far, we’ve discussed very simple use cases. However, we can get more creative:

到目前为止,我们已经讨论了非常简单的用例。然而,我们可以变得更有创意。

    static class IndicativeSentences extends ReplaceCamelCase {
        @Override
        public String generateDisplayNameForNestedClass(Class<?> nestedClass) {
            return super.generateDisplayNameForNestedClass(nestedClass) + "...";
        }

        @Override
        public String generateDisplayNameForMethod(Class<?> testClass, Method testMethod) {
            return replaceCamelCase(testClass.getSimpleName() + " " + testMethod.getName()) + ".";
        }
    }

The idea here is to create indicative sentences from the nested class and test method. In other words, the nested class name will be prepended to the test method name:

这里的想法是从嵌套类和测试方法中创建指示性的句子。换句话说,嵌套类的名称将被前置到测试方法的名称上。

class DisplayNameGeneratorUnitTest {

    @Nested
    @DisplayNameGeneration(DisplayNameGeneratorUnitTest.IndicativeSentences.class)
    class ANumberIsFizz {
        @Test
        void ifItIsDivisibleByThree() {
        }

        @ParameterizedTest(name = "Number {0} is fizz.")
        @ValueSource(ints = { 3, 12, 18 })
        void ifItIsOneOfTheFollowingNumbers(int number) {
        }
    }

    @Nested
    @DisplayNameGeneration(DisplayNameGeneratorUnitTest.IndicativeSentences.class)
    class ANumberIsBuzz {
        @Test
        void ifItIsDivisibleByFive() {
        }

        @ParameterizedTest(name = "Number {0} is buzz.")
        @ValueSource(ints = { 5, 10, 20 })
        void ifItIsOneOfTheFollowingNumbers(int number) {
        }
    }
}

Looking at the example, we use the nested class as a context for the test method. To better illustrate the results, let’s run the test:

看一下这个例子,我们使用嵌套类作为测试方法的上下文。为了更好地说明结果,我们来运行测试。

└─ Display name generator unit test ✓
   ├─ A number is buzz... ✓
   │  ├─ A number is buzz if it is one of the following numbers. ✓
   │  │  ├─ Number 5 is buzz. ✓
   │  │  ├─ Number 10 is buzz. ✓
   │  │  └─ Number 20 is buzz. ✓
   │  └─ A number is buzz if it is divisible by five. ✓
   └─ A number is fizz... ✓
      ├─ A number is fizz if it is one of the following numbers. ✓
      │  ├─ Number 3 is fizz. ✓
      │  ├─ Number 12 is fizz. ✓
      │  └─ Number 18 is fizz. ✓
      └─ A number is fizz if it is divisible by three. ✓

As we can see, the generator combined the nested class and test method names to create indicative sentences.

正如我们所看到的,生成器将嵌套的类和测试方法的名称结合起来,形成了指示性的句子。

4. Conclusion

4.总结

In this tutorial, we saw how to use the @DisplayNameGeneration annotation to generate display names for our tests. Furthermore, we wrote our own DisplayNameGenerator to customize the display name generation.

在本教程中,我们看到了如何使用@DisplayNameGeneration注解来为我们的测试生成显示名称。此外,我们写了自己的DisplayNameGenerator来定制显示名称的生成。

As usual, the examples used in this article can be found in the GitHub project.

像往常一样,本文中使用的例子可以在GitHub项目中找到。