참고문서 – Guide to JUnit 5 Parameterized Tests
개요
Parameterized tests는 단일 테스트 메서드를 다양한 매개변수로 여러 번 실행할 수 있게 해준다. 이를 통해 반복적인 테스트 코드를 줄이고, 다양한 입력값에 대한 테스트를 간편하게 수행할 수 있다.
기본 구조
@ParameterizedTest
@ValueSource(ints = {1, 3, 5, -3, 15, Integer.MAX_VALUE}) // 여섯 개의 숫자
void isOdd_ShouldReturnTrueForOddNumbers(int number) {
assertTrue(Numbers.isOdd(number));
}
- 해당 테스트는 메서드를 6번 실행한다.
@ValueSource배열에서 다른 값을number매개변수에 할당한다.
@ParameterizedTest어노테이션을 사용한다.@ValueSource를 통해 매개변수 소스를 정의한다.
매개변수 소스
Simple Values
ValueSource: 리터럴 값의 배열을 전달한다.
- 테스트 메서드에 한 번에 하나의 인수만 전달할 수 있다.
- null값을 전달할 수 없다.
- 지원하는 유형:
short,byte,int,long,float,double,char,String,Class
@ParameterizedTest
@ValueSource(strings = {"", " "})
void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input) {
assertTrue(Strings.isBlank(input));
}
NullSource & EmptySource: 단일 null 값 또는 빈 값을 전달한다.
- Collection 유형과 배열에 대해 빈 값을 제공할 수 있다.
@NullAndEmptySource를 이용해 null 값과 빈 값을 모두 전달할 수 있다.@ValueSource,@NullSource,@EmptySource를 결합하여 사용할 수 있다.
@ParameterizedTest
@NullAndEmptySource
@ValueSource(strings = {" ", "\t", "\n"})
void isBlank_ShouldReturnTrueForAllTypesOfBlankStrings(String input) {
assertTrue(Strings.isBlank(input));
}
EnumSource: 정의된 상수들을 전달한다.
@ParameterizedTest
@EnumSource(value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"})
void someMonths_Are30DaysLong(Month month) {
final boolean isALeapYear = false;
assertEquals(30, month.length(isALeapYear));
}
CsvSource: CSV (Comma Separated Value) 형식의 데이터를 전달한다.
- 기본적으로 쉼표 구분자를 사용하지만,
delimiter속성을 통해 이를 사용자 정의할 수 있다.
@ParameterizedTest
@CsvSource({"test,TEST", "tEst,TEST", "Java,JAVA"})
void toUpperCase_ShouldGenerateTheExpectedUppercaseValue(String input, String expected) {
String actualValue = input.toUpperCase();
assertEquals(expected, actualValue);
}
CsvFileSource: CSV 파일을 참조하여 데이터를 전달한다.
delimiter속성으로 사용자 정의할 수 있다.numLinesToSkip속성으로 CSV 파일을 읽을 때 줄을 건너뛸 수 있다.encoding속성을 사용하여 인코딩 값을 사용자 정의할 수 있다.
@ParameterizedTest
@CsvFileSource(resources = "/data.csv", numLinesToSkip = 1)
void toUpperCase_ShouldGenerateTheExpectedUppercaseValueCSVFile(String input, String expected) {
String actualValue = input.toUpperCase();
assertEquals(expected, actualValue);
}
Complex Values
MethodSource: 메서드를 매개변수로 전달한다.
MethodSource에 이름을 제공하지 않으면 JUnit은 테스트 메서드와 동일한 이름을 가진 소스 메서드를 검색하여 전달한다.
private static Stream<Arguments> provideStringsForIsBlank() {
return Stream.of(
Arguments.of(null, true),
Arguments.of("", true),
Arguments.of(" ", true),
Arguments.of("not blank", false)
);
}
@ParameterizedTest
@MethodSource("provideStringsForIsBlank")
void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input, boolean expected) {
assertEquals(expected, Strings.isBlank(input));
}
FieldSource: 정적 필드를 전달한다.
- JUnit 5.11부터 지원된다.
- 테스트 데이터를 정적 필드로 관리하고 재사용할 수 있다.
- 정적 필드의 이름이 테스트 이름과 일치하면 주석의 값을 생략할 수 있다.
static List<String> cities = Arrays.asList("Madrid", "Rome", "Paris", "London");
@ParameterizedTest
@FieldSource("cities")
void isBlank_ShouldReturnFalseWhenTheArgHasAtLeastOneCharacter(String arg) {
assertFalse(Strings.isBlank(arg));
}
디스플레이 이름 사용자 정의
@ParameterizedTest애노테이션의name속성을 통해 테스트의 디스플레이 이름을 사용자 정의할 수 있다.- 각 테스트 인스턴스의 결과를 명확하게 표현할 수 있다.
자리 표시자
- {displayName}: 메서드의 표시 이름으로 대체된다. 만약
@Display애노테이션이 제공된 경우, 해당 값이 사용된다. - {index}: 호출 인덱스로 대체된다. 첫 번째 실행의 호출 인덱스는 1, 두 번째는 2, 이런 식으로 계속된다.
- {arguments}: 인수 값의 전체 목록을 쉼표로 구분하여 나타내는 자리 표시자이다.
- {argumentsWithName}: 명명된 인수에 대한 자리 표시자이다.
arguments(named(NAME, ARG), …)구조로 생성된다. 주어진 이름과 실제 매개변수 이름을 출력한다. - {argumentSetName}: 팩토리 메서드
argumentSet에 제공된 첫 번째 매개변수(세트의 이름)에 대한 자리 표시자이다. - {argumentSetNameOrArgumentsWithName}:
argumentSet에 제공된 첫 번째 매개변수에 대한 자리 표시자이다. - {0}, {1}, …: 개별 인수에 대한 자리 표시자이다.
예제 코드
@ParameterizedTest(name = "{index} - {0} is 30 days long")
@EnumSource(value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"})
void someMonths_Are30DaysLong(Month month) {
final boolean isALeapYear = false;
assertEquals(30, month.length(isALeapYear));
}