테스트를 여러 번 반복해서 검증하고 싶다면, JUnit5에선 두개의 어노테이션을 통해 간단하게 지원해준다.
@RepeatedTest
@ParameterizedTest
먼저, RepeatedTest에 알아보자.
RepeatedTest
테스트 반복
@RepeatedTest(10)
void repeatTest() {
System.out.println("test");
}
RepeatedTest 어노테이션을 통해 손쉽게 해당 테스트코드를 10회 반복 할 수 있다.
여기서 RepeatedTest 어노테이션에서 RepetitionInfo 객체를 파라미터 값으로 넘겨 줄 수 있다. 해당 객체에는 현재 테스트의 수행횟수, 총 반복횟수를 알 수 있다.
@RepeatedTest(10)
void repeatTest(RepetitionInfo repetitionInfo ) {
System.out.println("test" + repetitionInfo.getCurrentRepetition()
+ "/" + repetitionInfo.getTotalRepetitions());
}
테스트명 변경
그리고, 반복되는 테스트의 명칭을 바꿔주려면 어노테이션 안에 인자 값에 명시해주면 된다.
@DisplayName("반복 테스트")
@RepeatedTest(value = 10, name= "{displayName} {currentRepetition} / {totalRepetitions}")
void repeatTest(RepetitionInfo repetitionInfo ) {
System.out.println("test" + repetitionInfo.getCurrentRepetition()
+ "/" + repetitionInfo.getTotalRepetitions());
}
이렇게 RepeatedTest 어노테이션 안에 있는 PlaceHolder를 사용하게 되면 손쉽게 테스트 명을 바꿀 수 있다.
이제 반복적인 테스트를 할 때마다, 다른 값을 주고 싶을때 ParameterizedTest라는 어노테이션을 사용하면 된다.
ParameterizedTest
@ParameterizedTest
@ValueSource(strings = {"날씨가", "많이", "추워지고", "있네요."})
void parameterizedTest(String message) {
System.out.println(message);
}
위와 같이 ValueSource를 사용하여 4개의 배열 값을 순차적으로 반복시키게 된다.
RepeatedTest 와 마찬가지로 테스트 이름을 변경하려면 아래와 같이 간단하게 소스를 수정하면 된다.
@DisplayName("파라미터 테스트")
@ParameterizedTest(name= "{index} {displayName}")
@ValueSource(strings = {"날씨가", "많이", "추워지고", "있네요."})
void parameterizedTest(String message) {
System.out.println(message);
}
ParameterizedTest는 아래의 어노테이션들을 통해 다양한 파라미터값을 지원해준다.
- @ValueSource
- @NullSource, @EmptySource, @NullAndEmptySource
- @EnumSource
- @MethodSource
- @CvsSource
- @CvsFileSource
- @ArgumentSource
몇가지 핵심 어노테이션만 알아보자!
@NullSource, @EmptySource, @NullAndEmptySource
Null값과 빈값을 파라미터로 전달한다.
@NullSource, @EmptySource 두개의 어노테이션을 @NullAndEmptySource 하나로 축약해서 사용할 수 있다.
@DisplayName("파라미터 테스트")
@ParameterizedTest(name= "{index} {displayName} message= {0}")
@ValueSource(strings = {"날씨가", "많이", "추워지고", "있네요."})
@NullSource
@EmptySource
void parameterizedTest(String message) {
System.out.println(message);
}
@ValueSource, @CvsSource
값을 전달해 주는 어노테이션으로 사용된다.
여기서 ParameterizedTest는 인자 값 타입에 대한 두가지의 형변환이 존재한다.
- 암묵적인 타입변환
- 명시적인 타입 변환
암묵적인 타입변환은 기본적으로 string으로 입력된 파라미터 값을 자동으로 형변환하여 반환해주는 것이다.
해당 Case에 대한 가이드는 아래 레퍼런스를 참조하면 될 것 같다.
만약 개발자가 생성한 클래스와 같은 객체로 형변환을 해주고 싶을경우, SimpleArgumentConverter를 상속 받은 구현체를 제공해야 한다. 이런 경우를 명시적인 타입 변환이라 한다.
그러면 예외적으로 개발자가 생성한 클래스로 형변환을 하는 구현체를 만들어보자.
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class StudyTest {
static class SutdyConverter extends SimpleArgumentConverter{
@Override
protected Object convert(Object source, Class<?> targetType) throws ArgumentConversionException {
assertEquals(Study.class, targetType, "Can only convert to study");
return new Study(Integer.parseInt(source.toString()));
}
}
@DisplayName("파라미터 테스트")
@ParameterizedTest(name= "{index} {displayName} message= {0}")
@ValueSource(ints = {10,20,40})
void parameterizedTest(@ConvertWith(SutdyConverter.class) Study study) {
System.out.println(study.getLimit());
}
}
위와 같이 구현체를 생성하고, @ConvertWith라는 어노테이션에 구현체를 명시해주면 손쉽게 Integer타입의 Paramter값들이 Study 객체로 형변환이 일어난다.
SimpleArgumentConverter은 하나의 파라미터 값을 전달받을 때 위와 같이 사용할 수 있고, 만약 2개 이상의 파라미터를 전달 받는다면 @CsvSource를 사용하면 된다.
Study.class 수정
public class Study {
private StudyStatus status;// = StudyStatus.DRAFT;
private int limit;
private String name;
public Study(int limit) {
if(limit < 0) {
throw new IllegalArgumentException("limit은 0보다 커야합니다!");
}
this.limit = limit;
}
public Study(int limit, String name) {
this.limit = limit;
this.name = name;
}
public StudyStatus getStatus() {
return this.status;
}
public int getLimit() {
return this.limit;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Study [status=" + status + ", limit=" + limit + ", name=" + name + "]";
}
}
Tests.class
@DisplayName("파라미터 테스트")
@ParameterizedTest(name= "{index} {displayName} message= {0}")
@CsvSource({"10, '자바 스터디'", "20, 스프링"})
void parameterizedTest(Integer limit, String name) {
Study study = new Study(limit, name);
System.out.println(study);
}
위와 같이, @CsvSource를 사용하여 2개의 파라미터 값을 전달 받을 수 있다.
만약 파라미터를 하나의 객체로 전달 받고 싶다면 ArgumentsAccessor를 파라미터로 전달 받으면 된다.
@DisplayName("파라미터 테스트")
@ParameterizedTest(name= "{index} {displayName} message= {0}")
@CsvSource({"10, '자바 스터디'", "20, 스프링"})
void parameterizedTest(ArgumentsAccessor argumentsAccessor) {
Study study = new Study(argumentsAccessor.getInteger(0), argumentsAccessor.getString(1));
System.out.println(study);
}
ArgumentsAccessor 객체를 파라미터로 전달 받아, 해당 객체 안에서 차례대로 인자 값을 추출할 수 있다.
만약, 파라미터 자체를 개발자가 생성한 클래스인 Study로 전달 받고 싶다면, 커스텀한 Aggregator를 구현하면된다.
static class StudyAggregator implements ArgumentsAggregator{
@Override
public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context)
throws ArgumentsAggregationException {
Study study = new Study(accessor.getInteger(0), accessor.getString(1));
return study;
}
}
@DisplayName("파라미터 테스트")
@ParameterizedTest(name= "{index} {displayName} message= {0}")
@CsvSource({"10, '자바 스터디'", "20, 스프링"})
void parameterizedTest(@AggregateWith(StudyAggregator.class) Study study) {
System.out.println(study);
}
AggregateWith로 구현한 Aggregator를 명시하면 손쉽게 형변환이 일어난다.
'Framework > ✔️JUnit5' 카테고리의 다른 글
TDD를 위한 JUnit5 사용법 3 - 조건, 환경에 따른 테스트 실행 (0) | 2022.09.03 |
---|---|
TDD를 위한 JUnit5 사용법 2 - Assertion (0) | 2022.08.15 |
TDD를 위한 JUnit5 사용법 1 - JUnit5 개요 및 Naming Annotation (0) | 2022.08.14 |
댓글