🚀 오늘은 다양한 매개변수 케이스를 하나의 테스트 메소드에서 주입시켜주는
@ParameterizedTest 어노테이션의 다양한 케이스들의 가이드를 기록해보고자 합니다...!!
[목차]
- @Parameterized란
- @Parameterized 가이드
- @Parameterized 공급자 종류
@Parameterized란
- @ParameterizedTest 어노테이션은 Junit 에서 다양한 매개변수들에 대한 경우를 테스트할 수 있도록 제공해주는 어노테이션입니다.
- @ParameterizedTest 주석이 달린 메소드는 매개변수화된 테스트 메소드임을 의미하고 Private, Static 이 아니어야 합니다.
@Parameterized 시작 가이드
의존성 추가
- 먼저 JUnit Jupiter Params 의존성을 추가해야 @ParameterizedTest 를 사용할 수 있습니다.
Gradle - build.gradle
testCompile("org.junit.jupiter:junit-jupiter-params:5.7.0")
@Parameterized 다양한 공급자들
- @ParameterizedTest 메소드는 @ArgumentsSource 또는 이에 사응하는 합성 주석(ex - @ValueSource, @CsvSource 등) 을 통해 하나 이상의 ArgumentsProvider 를 지정해주어야합니다.
- 공급자는 매개 변수화된 테스트 메소드를 호출하는데 사용할 Argument Strem 을 반환해야할 책임이 있습니다.
- ✨ 즉, @Parameterized 를 사용한다면, 꼭 어떤 매개변수를 사용해 줄 것인지(@ArgumentsSource 들) 주입해주어야한다는 뜻입니다!
Provider
위에서도 말했다시피 @Parameterized 를 사용하기 위해서는 매개변수(실제값을 담은 argument라 칭함) 를 넘겨주어야하고 공식문서에서는 이를 ArgumentsProvider 라 칭하고 있습니다.
이 ArgumentProvider 로 사용될 수 있게 주석으로 만들어놓은 것이 argument source 들이고 ArgumentProvider로 사용할 수 있는 arguments source 는 @ArgumentsSoruce로 등록할 수 있다고 합니다.
argument source 들의 종류
- ValueSource
- MethodSource
- NullAndEmptySource
- CsvSource
- CsvFileSource
- EnumSource
- 등등..
@Parameterized - Argument Source 가이드
인자 @Parmaterized를 직접적으로 사용해서 테스트해보는 방법을 알아보겠습니다.
1. @ValueSource
- @ValueSource는 리터럴 값 배열에 대한 액세스를 제공하는 ArgumentsSource 입니다.
- 지원되는 유형에는 shorts , bytes , ints , longs , floats , doubles , chars , booleans , strings 및 classes 가 포함됩니다.
- @ValueSource 는 하나의 인자를 받을 때 유용하게 사용됩니다. String을 제외한 원시타입 변수들을 주입받을 수 있습니다.
- @ValueSource를 사용할때는 2번째 문장처럼, 소문자에 "s" 를 붙여서 타입을 명시합니다.
@ParameterizedTest
@ValueSource(strings = {"1", "2", "3", "0", "21332"})
public void sizeOne(final String numbers) {
//given
String[] input = {numbers};
//when
Calculator calculator = new Calculator();
//then
assertThat(calculator.strSum(input)).isEqualTo(Integer.valueOf(numbers));
}
2. @MethodSource
- @MethodSource는 이 주석이 선언된 클래스의 팩토리 메소드 또는 정규화된 메소드 이름이 참조하는 외부 클래스의 정적 팩토리 메소드에서 리턴된 값에 대한 액세스를 제공하는 ArgumentSouce 입니다.
- @ValueSource 에서는 다루지 못하는 Object를 매개변수로 주입받을 수 있습니다.
- Stream<Arguments> 를 반환하는 별도의 정적 메소드가 필요합니다.
- @MethodSource("주입해주는 메소드 명") 으로 명시적으로 선언해주어도 되고, 아래 예시처럼 메소드 명이 같으면 자동으로 주입되기도 합니다.
@ParameterizedTest
@MethodSource
@DisplayName("계산기는 배열로 들어온 음수 or 숫자가 아니면 예외를 던진다.")
void calculator_sum_x(String[] numbers) {
Calculator calculator = new Calculator();
//then
assertThatThrownBy(() -> calculator.strSum(numbers))
.isInstanceOf(RuntimeException.class);
}
private static Stream<Arguments> calculator_sum_x() {
return Stream.of(
Arguments.of((Object) new String[]{"-1"}),
Arguments.of((Object) new String[]{"1,-1"}),
Arguments.of((Object) new String[]{"dk"}),
Arguments.of((Object) new String[]{"0", "1", "adf"}),
Arguments.of((Object) new String[]{"1", "df", "-1"}),
Arguments.of((Object) new String[]{"A", "B", "C", "D", "E"})
);
}
3. @NullAndEmptySource
- @NullAndEmptySource는 파라미터에 null 값을 주입해주는 @NullSource 와 빈값을 주입하는 @EmptySource 의 기능을 합친 주석입니다.
- 아래처럼 사용하면 코드의 중복을 족흠은 줄일수 있습니다
2가지 경우를 모두 테스트하고, 명시적으로 선언해줄 떄
@Test
@DisplayName("들어온 값이 빈값일 경우 false")
void preEmptyCheck() {
//given
String input1 = "";
Input input = new Input();
assertThat(input.isEmpty(input1)).isFalse();
}
@Test
@DisplayName("들어온 값이 null일 경우 false")
void preNullCheck() {
//given
String input1 = null;
Input input = new Input();
assertThat(input.isEmpty(input1)).isFalse();
}
@NullAndEmptySource를 사용할 때 - 코드 확 짧아져버림
@ParameterizedTest
@NullAndEmptySource
@DisplayName("들어온 값이 null 이거나 빈 값일 경우")
void preBlankCheck(String input1) {
Input input = new Input();
assertThat(input.isEmpty(input1)).isFalse();
}
4. @CsvSource
- @CsvSource 는 value 속성 또는 textBlock 속성을 통해 제공된 하나 이상의 CSV 행에서 쉼표(,)로 구분된 값(CSV)를 읽는 ArgumentSource 입니다.
- 구분자는 delimter() 를 이용하여 커스텀하게 지정할 수 있습니다.
- 👏🏻 쉽게 말해 @CsvSource 는, 테스트할 파라미터 값과, 그 값에 따른 결과값 까지 변경해서 더 다양하게 테스트가 가능합니다.
숫서대로 파라미터에 들어가는 @CsvSource
@ParameterizedTest
@CsvSource({
"apple, 1",
"banana, 2",
"'lemon, lime', 0xF1",
"strawberry, 700_000",
})
void test(String fruit, int rank) {
// ...
}
구분자를 커스텀하게 지정해 줄 수 있고, 결과값까지 주입받아서 다양한 테스트가 가능
@ParameterizedTest
@CsvSource(value = {"1:true", "2:true", "3:true", "4:false", "5:false"}, delimiter = ':')
void set_contains_true_false(int element, boolean expected) {
assertThat(numbers.contains(element)).isEqualTo(expected);
}
5. @CsvFileSource
- @CsvFileSource 는 하나 이상의 클래스 경로 resources 또는 files 에서 쉼표로 구분된 값(CSV) 파일을 로드하는데 사용되는 ArgumentsSource 입니다.
- #기호로 시작하는 줄은 주석으로 해석되어 무시된다고 합니다.
- 👏🏻 쉽게말해, resource 폴더 경로에있는 .csv 파일을 로드하여 구분자로 넣어줍니다.
- 대용량 테스트 처리에 용이해보입니다.
정의된 .csv 파일 예시
//two-column.csv
Country, reference
Sweden, 1
Poland, 2
"United States of America", 3
@CsvSource 예시
@ParameterizedTest
@CsvFileSource(resources = "/two-column.csv", numLinesToSkip = 1)
void testCsvFileSourceResource(String country, int reference) {
}
@ParameterizedTest
@CsvFileSource(files = "src/test/resources/two-column.csv", numLinesToSkip = 1)
void testCsvFileSourceFiles(String country, int reference) {
}
6. @EnumSource
- @EnumSource 는 Enum 의 상수에 대한 ArgumentsSource 입니다.
- enum 유형은 Value 속성을 사용하여 명시적으로 지정할 수 있고, 그렇지 않으면 @ParameterizedTest 메소드의 첫 번째 매개변수의 선언된 유형이 사용됩니다.
- 열거형 상수 집합은 names 와 mode 속성을 통해 제한할 수 있습니다.
@ParameterizedTest
@EnumSource(Month.class) // passing all 12 months
void getValueForAMonth_IsAlwaysBetweenOneAndTwelve(Month month) {
int monthNumber = month.getValue();
assertTrue(monthNumber >= 1 && monthNumber <= 12);
}
@ParameterizedTest
@EnumSource(value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"})
void someMonths_Are30DaysLong(Month month) {
final boolean isALeapYear = false;
assertEquals(30, month.length(isALeapYear));
}
@ParameterizedTest
@EnumSource(
value = Month.class,
names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER", "FEBRUARY"},
mode = EnumSource.Mode.EXCLUDE)
void exceptFourMonths_OthersAre31DaysLong(Month month) {
final boolean isALeapYear = false;
assertEquals(31, month.length(isALeapYear));
}
*참고
- parameterized 가이드 : https://gmlwjd9405.github.io/2019/11/27/junit5-guide-parameterized-test.html
- @CsvFileSource 예제 : https://effortguy.tistory.com/118
'Spring > Test-Driven Develop' 카테고리의 다른 글
[Junit] @ParameterizedTest 객체에 값을 자동으로 넣어주는 Auto Param - @autosource (0) | 2022.12.27 |
---|---|
[Junit] Test Fixture 란 ❓ (0) | 2022.10.28 |
[Spring] java private 메소드 테스트 코드 작성하기 (4) | 2022.08.24 |
[Spring] 백엔드 부하 테스트 해보기 - nGrinder(with aws, jmeter) (4) | 2022.03.14 |
[Spring boot] 테스트 코드 작성 (2) - Mock, Mockito, MockMVC (0) | 2022.02.03 |