Labs ICT
โญ Pro Login

@DisplayName and Test Naming

You already saw @DisplayName in previous lessons, but let us dive deeper into how to use it effectively and explore other naming features in JUnit 5. Good test names are one of the most underrated aspects of testing.

Why Test Names Matter

Imagine looking at this test report:


Tests run: 15
  - test1 PASSED
  - test2 FAILED
  - test3 PASSED
  - test4 PASSED
  - test5 PASSED
    

Now imagine this one:


Tests run: 15
  - "Should add two positive numbers" PASSED
  - "Should throw exception for negative price" FAILED
  - "Should return empty list when no items exist" PASSED
  - "Should format currency with two decimals" PASSED
  - "Should reject null user name" PASSED
    

The second report tells you exactly what is broken and what the intention was. Test names are documentation.

@DisplayName in Action


import org.junit.jupiter.api.*;

@DisplayName("Calculator Operations")
class CalculatorTest {

    Calculator calc = new Calculator();

    @Test
    @DisplayName("Addition: should return sum of two positive numbers")
    void addPositiveNumbers() {
        assertEquals(5, calc.add(2, 3));
    }

    @Test
    @DisplayName("Addition: should handle negative numbers correctly")
    void addNegativeNumbers() {
        assertEquals(-1, calc.add(-3, 2));
    }

    @Test
    @DisplayName("Division: should throw ArithmeticException when dividing by zero")
    void divideByZero() {
        assertThrows(ArithmeticException.class,
            () -> calc.divide(10, 0));
    }

    @Nested
    @DisplayName("Multiplication Tests")
    class MultiplicationTests {
        @Test
        @DisplayName("Should multiply two positive numbers")
        void multiplyPositive() {
            assertEquals(6, calc.multiply(2, 3));
        }

        @Test
        @DisplayName("Should return zero when multiplied by zero")
        void multiplyByZero() {
            assertEquals(0, calc.multiply(5, 0));
        }
    }
}
    

Naming Conventions

Here are some popular naming styles. Pick one and stick with it:


// 1. Behavior-driven (recommended)
@DisplayName("Should [expected behavior] when [condition]")
void shouldReturnSumWhenGivenTwoNumbers() { }

// 2. Given-When-Then
void givenValidUser_whenLogin_thenReturnsToken() { }

// 3. Method-Under-Test style
void add_withPositiveNumbers_returnsSum() { }

// 4. Simple descriptive
void additionOfTwoNumbers() { }

// 5. BDD style with underscores
void login_with_valid_credentials_returns_token() { }
    

The key principle: when a test fails, the name should tell you what went wrong and what the expected behavior was.

Combining @DisplayName with @Nested

The real power of @DisplayName shows when combined with @Nested:


@DisplayName("User Registration")
class RegistrationTest {

    @Nested
    @DisplayName("when email is valid")
    class ValidEmail {

        @Test
        @DisplayName("should register successfully")
        void registerSuccessfully() {
            // ...
        }

        @Test
        @DisplayName("should send confirmation email")
        void sendsConfirmationEmail() {
            // ...
        }
    }

    @Nested
    @DisplayName("when email is invalid")
    class InvalidEmail {

        @Test
        @DisplayName("should reject registration")
        void rejectsRegistration() {
            // ...
        }

        @Test
        @DisplayName("should return descriptive error message")
        void returnsErrorMessage() {
            // ...
        }
    }
}
    

This produces a beautifully structured test report that reads like documentation:


User Registration
โ”œโ”€โ”€ when email is valid
โ”‚   โ”œโ”€โ”€ should register successfully                    PASSED
โ”‚   โ””โ”€โ”€ should send confirmation email                   PASSED
โ””โ”€โ”€ when email is invalid
    โ”œโ”€โ”€ should reject registration                       PASSED
    โ””โ”€โ”€ should return descriptive error message          FAILED
    

Tips for Good Test Names

  • Use complete sentences with @DisplayName
  • Start with "Should" for assertions
  • Include the scenario and expected outcome
  • Use @Nested to group related tests by context
  • Avoid vague names like "test1", "test2", or "myTest"
  • Do not repeat the class name in every test name

๐Ÿงช Quick Quiz

Which annotation provides a custom display name for a test class or method?