Server/JUnit, Spock

JUnit5 - Parameterized Tests

JaeHoney 2022. 5. 29. 12:23

Parameterized Tests

@ParameterizedTest 애노테이션을 @Test 애노테이션 대신 사용하면 여러 개의 파라미터 값에 대해 각각 테스트를 수행하는 코드를 간편하게 작성할 수 있다.

@ParameterizedTest
@ValueSource(ints = {0, 1, 3, 5, 15, -10, -200 Integer.MAX_VALUE})
void isInteger_ShouldReturnTrueForIntegers(int number) {
    assertTrue(Numbers.isInteger(number));
}

ValueSource

@ValueSource 애노테이션에 지정한 배열을 파라미터 값으로 넘기면 각 인수에 대해 테스트를 각각 실행한다.

@ParameterizedTest
@ValueSource(strings = {"", "  ", "  "})
void isBlank_ShouldReturnTrueForEmptyOrBlankStrings(String input) {
    assertTrue(Strings.isBlank(input));
}

이 때 인자로는 Literal values(short, byte, int, long, float, double ... java.lang.String, java.lang.Class 등)를 사용한다.

 

@ValuesSources 뒤에 리터럴의 타입을 적은 후 배열을 넘기면 된다.

 

Null & Empty Source

다음 애노테이션들은 Null 또는 Empty String / Empty Collection 등을 파라미터로 받아 테스트할 때 사용한다.

  • @NullSource를 사용하면 Null값을 인수로 테스트할 수 있다.
  • @EmptySource를 사용하면 Empty String이나 Empty Array로 테스트할 수 있다.
  • @NullAndEmptySource는 @NullSource와 @EmptySource가 결합한 형태이다.
@ParameterizedTest
@NullAndEmptySource
void isBlank_ShouldReturnTrueForNullAndEmptyStrings(String input) {
    assertTrue(Strings.isBlank(input));
}

 

Enum Source

@EnumSource을 사용하면 Enum의 값 여러개를 배열로 전달받을 수 있다.

@ParameterizedTest
@EnumSource(Week.class)
void getValueForWeek_IsAlwaysBetweenOneAndSeven(Week week) {
    int weekValue = week.getValue();
    assertTrue(weekValue >= 1 && weekValue <= 7);
}

위의 결과는 모든 Enum 값을 전부 전달해서 테스트한다.

 

@EnumSource의 names 옵션을 사용하면 원하는 요소만 선택할 수 있고, mode 옵션을 사용하면 해당 요소를 제외할 수도 있다.

@ParameterizedTest
@EnumSource(
    value = Week.class,
    names = {"SATURDAY", "SUNDAY"},
    mode = EnumSource.MODE.EXCLUDE
)
void getValueForWeek_IsAlwaysBetweenOneAndSeven(Week week) {
    assertTrue(week.isWeekday());
}

 

Method Source

이제껏 배운 기능들로 복잡한 object 리스트를 제공하여 테스트하는 것은 어렵다. @MethodSource를 사용하면 이를 간단하게 구현할 수 있다.

@ParameterizedTest
@MethodSource("paramsForIsBlank")
void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input, boolean expected) {
     assertEquals(expected, Strings.isBlank(input));
}

private static Stream<Arguments> paramsForIsBlank() {
    return Stream.of(
       Arguments.of(null, true)
       Arguments.of("", true),
       Arguments.of("  ", true),
       Arguments.of("not blank", false)
    );
}

@MethodSource는 여러 가지 인수나 복잡한 인수를 생성할 때 사용한다. 속성으로 메서드 이름을 정확하게 명시해야하고, 애노테이션이 컴파일 시 메소드를 불러와야 하므로 static method여야 한다. Stream<Arguments>나 List와 같은 컬렉션도 반환할 수 있다.

 

해당 방법을 사용하면 다른 테스트 클래스 간에 인수를 공유하는 것도 가능하다.

 


잘 사용하지 않지만 @CsvSource 애노테이션을 사용하면서 구분자를 사용해서 인수를 삽입하는 방법도 있고 다양하다.

 

Junit5를 잘 익히면 테스트 코드를 우아하게 작성하는데 도움이 많이 되는 것 같다.

 


Reference