들어가며
특정 메서드의 결괏값을 확인할 때 반복문을 사용하거나 여러 개의 단위 테스트를 만들어 엣지 케이스와 올바른 값을 확인합니다. 하지만 하나의 테스트에서 진행할 수 있는 방법이 존재합니다. 예를 들어 소수 값을 확인하는 메서드가 다음과 같습니다.
public class Numbers {
public static boolean isOdd(int number) {
return number % 2 != 0;
}
}
소수를 테스트 하기위해 여러 테스트를 만들거나 반복문을 사용하지 않고 다음과 같이 테스트가 가능합니다.
@ParameterizedTest
@ValueSource(ints = {1, 3, 5, -3, 15, Integer.MAX_VALUE}) // six numbers
void isOdd_ShouldReturnTrueForOddNumbers(int number) {
assertTrue(Numbers.isOdd(number));
}
테스트 메소드를 하나만 만들고 간결해 보이지 않나요? 지금부터 JUnit5에서 지원하는 ParameterizedTest에 대해 알아보겠습니다.
Argument Sources
@ValueSource
@valueSource 어노테이션을 사용하면 파라미터에 원하는 데이터 타입의 값을 넘겨줄 수 있습니다.
- short (with the shorts attribute)
- byte (bytes attribute)
- int (ints attribute)
- long (longs attribute)
- float (floats attribute)
- double (doubles attribute)
- char (chars attribute)
- java.lang.String (strings attribute)
- java.lang.Class (classes attribute)
예시 코드는 다음과 같습니다.
@ParameterizedTest
@ValueSource(strings = {"A", "B", "C"})
void containsABC(String value) {
assertThat(Set.of("A", "B", "C")).contains(value);
}
@Null and Empty Values
공백 문자열이나 Null을 확인하기 위한 어노테이션입니다.
@ParameterizedTest
@NullAndEmptySource
void isBlank_CheckedNullAndEmpty(String input) {
assertTrue(Strings.isBlank(input));
}
추가로 @valueSource 어노테이션을 함께 사용도 가능합니다.
@ParameterizedTest
@NullAndEmptySource
@ValueSource(strings = {"\n", "\t", " "})
void isBlank_CheckedNullAndEmpty(String input) {
assertTrue(Strings.isBlank(input));
}
@EnumSource
Enum이 가지는 상수들에 대한 테스트도 가능합니다. 다음과 같이 계절을 표현하는 enum클래스를 테스트해보겠습니다.
enum Season {
SPRING(1), SUMMER(2), FALL(3), WINTER(4);
}
@ParameterizedTest
@EnumSource(value = Season.class)
void getSeasonValue(Season season) {
assertTrue(1 <= season.getNumber() && season.getNumber() <= 4);
}
season의 모든 value값을 확인하였습니다. enum의 특정 상수만 테스트하는 방법도 있습니다.
@ParameterizedTest
@EnumSource(value = Season.class, names = "SPRING")
void getSeasonValue(Season season) {
assertTrue(season == Season.SPRING);
}
이번엔 특정 상수값을 제외하여 테스트해보겠습니다. 예시의 코드만 읽어도 기능을 충분히 짐작할 수 있습니다.
@ParameterizedTest
@EnumSource(
value = Season.class,
names = {"SPRING", "SUMMER", "FALL"},
mode = EnumSource.Mode.EXCLUDE)
void getSeasonValue(Season season) {
assertTrue(season == Season.WINTER);
}
정규식을 사용해서 원하는 상수값을 파라미터로 넘길 수 있습니다. 이때 mode는 사용하고자 하는 목정에 따라 변경해주시면 됩니다.
@ParameterizedTest
@EnumSource(value = Season.class, names = "S.+", mode = EnumSource.Mode.MATCH_ALL)
void getSeasonValue(Season season) {
EnumSet<Season> enumSet = EnumSet.of(Season.SPRING, Season.SUMMER);
assertTrue(enumSet.contains(season));
}
CSV Literals
위에서 살펴보았던 @ValueSource 기능은 파라미터로 하나의 값을 넘길 수 있었습니다. 던지는 파라미터마다 다른 결괏값을 가진다면 어떻게 처리해야 할까요? @CsvSource 어노테이션을 사용해서 결괏값을 전달할 수 있습니다. csv라는 키워드에서 눈치를 챌 수 있습니다. 구분자를 통해서 전달 값과 결괏값을 파라미터로 전달할 수 있습니다. 기본으로 쉼표(,)를 구분으로 분리를 하며 다른 구분자를 사용하고 싶다면 delimiter에 다른 옵션을 주시면 됩니다. 코드로 살펴보겠습니다.
@ParameterizedTest
@CsvSource(value = {"test,TEST", "tEst,TEST", "Java,JAVA"})
void toUpperCase(String actual, String expected) {
assertEquals(actual.toUpperCase(), expected);
}
@ParameterizedTest
@CsvSource(value = {"test:TEST", "tEst:TEST", "Java:JAVA"}, delimiter = ':')
void toUpperCase(String actual, String expected) {
assertEquals(actual.toUpperCase(), expected);
}
마치며
우테코에서 페어 프로그래밍으로 자동차 경주 미션을 진행하며 예제 코드와 페어가 사용하는 것을 보고 학습해 보았습니다. 생각보다 사용하는 방법이 어렵지 않아 유용하게 사용할 거 같습니다. 이외에도 csv file을 직접 만들어 테스트할 수 있고 메서드를 만들거나 커스텀한 어노테이션도 사용이 가능합니다. https://www.baeldung.com/parameterized-tests-junit-5 문서를 참고하였습니다.
'개발 > Java' 카테고리의 다른 글
[Java] 제네릭 (2) | 2022.03.02 |
---|---|
[JUnit] @ParameterizedTest - @MethodSource 사용하기 (0) | 2022.02.27 |
[Java] package, import (2) | 2022.02.15 |
[Java] 리플렉션 (reflection) 개념 이해하기 (0) | 2022.01.29 |
[Java] Record (0) | 2022.01.20 |