Java >> Java tutorial >  >> Tag >> JUnit

JUnit Custom Display Name Generator API

1. Oversigt

JUnit 5 har god support til at tilpasse testklasse- og testmetodenavne. I denne hurtige vejledning vil vi se, hvordan vi kan bruge JUnit 5 brugerdefinerede visningsnavne via @DisplayNameGeneration annotation.

2. Generering af displaynavne

Vi kan konfigurere brugerdefinerede visningsnavne via @DisplayNameGeneration anmærkning . Det er dog godt at være opmærksom på, at @DisplayName annotering har altid forrang over enhver visningsnavngenerator.

Til at begynde med giver JUnit 5 en DisplayNameGenerator.ReplaceUnderscores klasse, der erstatter eventuelle understregninger i navne med mellemrum. Lad os tage et kig på et eksempel:

@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() {
        }
    }
}

Nu, når vi kører testen, kan vi se, at genereringen af ​​displaynavne gjorde testoutputtet mere læsbart:

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

3. Generator af tilpasset visningsnavn

For at kunne skrive en brugerdefineret visningsnavngenerator skal vi skrive en klasse, der implementerer metoderne i DisplayNameGenerator grænseflade . Interfacet har metoder til at generere navnet på en klasse, en indlejret klasse og en metode.

3.1. Udskiftning af kamelhus

Lad os starte med en simpel generator for visningsnavne, der erstatter navne på kamelhuse med læsbare sætninger. Til at begynde med kan vi udvide DisplayNameGenerator.Standard klasse :

    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();
        }
    }

I ovenstående eksempel kan vi se de metoder, der genererer forskellige dele af visningsnavnet.

Lad os skrive en test til vores generator:

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

    @Test
    void camelCaseName() {
    }
}

Dernæst, når vi kører testen, kan vi se, at navnene på kamelhusene er blevet erstattet med læsbare sætninger :

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

3.2. Vejledende sætninger

Indtil videre har vi diskuteret meget simple use cases. Vi kan dog blive mere kreative:

    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()) + ".";
        }
    }

Ideen her er at skabe vejledende sætninger fra den indlejrede klasse og testmetode . Med andre ord vil det indlejrede klassenavn blive sat foran testmetodenavnet:

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) {
        }
    }
}

Ser vi på eksemplet, bruger vi den indlejrede klasse som en kontekst for testmetoden. For bedre at illustrere resultaterne, lad os køre testen:

└─ 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. ✓

Som vi kan se, kombinerede generatoren de indlejrede klasse- og testmetodenavne for at skabe vejledende sætninger.

4. Konklusion

I denne øvelse så vi, hvordan man bruger @DisplayNameGeneration annotering for at generere visningsnavne til vores tests. Desuden skrev vi vores egen DisplayNameGenerator for at tilpasse generering af visningsnavne.

Som sædvanlig kan de eksempler, der er brugt i denne artikel, findes i GitHub-projektet.


Java tag