알고리즘을 풀 때 단위 테스트를 통해 매 실행시 케이스 입력의 귀찮음을 최소화하고자 했습니다.
@ParameterizedTest
- @ParameterizedTest 어노테이션을 사용하여 여러 개의 파라미터를 하나의 테스트를 통해 확인할 수 있습니다
- @Test 어노테이션 대신 @ParameterizedTest를 명시해주면 됩니다
- @ParameterzedTest를 사용하기 위해서는 하나 이상의 Source 어노테이션을 붙여줘야합니다
- Source 어노테이션에는 @ValueSource, @MethodSource, @NullSource, @EmptySource 등등이 있습니다
@MethodSource
저는 2차원 배열의 케이스를 입력하고자 @MethodSource 어노테이션을 사용하게 됐습니다.
- @MethodSource 어노테이션은 테스트 클래스 또는 외부 클래스(?!!!)의 팩토리 메서드를 참조할 수 있습니다.
팩토리 메서드 조건
- 반드시 static 으로 만들어줘야합니다
- 단, @TestInstance(Lifecycle.PER_CLASS (테스트의 생명주기와 관련된 어노테이션)가 있을 경우엔 필요 없습니다
- 인자는 없어야합니다
- Stream 타입으로 반환해주어야합니다
테스트 메서드의 인자가 하나일 경우
public class ParameterizedTestEx {
@ParameterizedTest
@MethodSource("hello")
void parameterizedTest() {
}
static Stream<String> hello() {
return Stream.of("hi", "hello");
}
}
- Stream의 of() 메서드를 이용해 파라미터로 사용하고 싶은 인자를 넣어줍니다
인자가 여러 개일 경우
public class ParameterizedTestEx {
@ParameterizedTest
@MethodSource("hello")
void parameterizedTest() {
}
static Stream<int[][]> testWithMultiArray() {
return Stream.of(
new int[][]{
{1, 0, 1, 1, 1}, {1, 0, 1, 0, 1}, {1, 0, 1, 1, 1}, {1, 1, 1, 0, 0}, {0, 0, 0, 0, 1}}
},
new int[][] {
{1, 0, 1, 1, 1}, {1, 0, 1, 0, 1}, {1, 0, 1, 1, 1}, {1, 1, 1, 0, 1}, {0, 0, 0, 0, 1}
}
);
}
}
잘못된 예를 보여주기 위한 예시입니다
- 인자가 여러 개인 것 중 제가 사용하고 싶었던 인자 값은 int[][] 였습니다. 하지만 JUnit Jupiter 5.3.1 버전부터 다차원 배열을 Stream 에 반환할 수 없게 되었습니다
public class ParameterizedTestEx {
@ParameterizedTest
@MethodSource("hello")
void parameterizedTest() {
}
static Stream<Object[]> testWithMultidimensionArray() {
return Stream.of(
new Object[]{
new int[][]{
{1, 0, 1, 1, 1}, {1, 0, 1, 0, 1}, {1, 0, 1, 1, 1}, {1, 1, 1, 0, 0}, {0, 0, 0, 0, 1}}
},
new Object[] {
new int[][] {
{1, 0, 1, 1, 1}, {1, 0, 1, 0, 1}, {1, 0, 1, 1, 1}, {1, 1, 1, 0, 1}, {0, 0, 0, 0, 1}
}
}
);
}
}
- stackoverflow 를 통해 Obejct[] 에 다차원 배열을 생성하여 반환해주는 방법이 있다는 걸 알게되었습니다
이렇게 하면 테스트를 위한 인자는 다 준비했다고 생각했습니다.
하지만 @ParameterizedTest 의 인자들은 실행 순서가 보장되지 않는 것 같았습니다

- 이처럼 @ParameterizedTest 를 통해 여러 개의 인자 값을 받고 예상되는 결과 값을 테스트 해보았으나 테스트가 틀리는 문제가 발생합니다
해결 방법
코드스쿼드 동료 나단의 도움으로 해결할 수 있었습니다!
static Stream<Arguments> testWithMultiArray() {
return Stream.of(
arguments(new int[][]{{1, 0, 1, 1, 1}, {1, 0, 1, 0, 1}, {1, 0, 1, 1, 1}, {1, 1, 1, 0, 0}, {0, 0, 0, 0, 1}}, -1),
arguments(new int[][] {{1, 0, 1, 1, 1}, {1, 0, 1, 0, 1}, {1, 0, 1, 1, 1}, {1, 1, 1, 0, 1}, {0, 0, 0, 0, 1}}, 11)
);
}
- 반환 값으로 Stream 에 Arguments 의 팩토리 메서드인 arguments 에 테스트 할 케이스와 해당 케이스가 반환할 값을 넣어주면 되는 문제였습니다
@ParameterizedTest
@MethodSource()
void testWithMultiArray(int[][] arr, int result) {
assertThat(s.solution(arr)).isEqualTo(result);
}

- 위처럼 테스트 메서드의 인자 값으로 arguments 에 입력했던 타입과 변수명을 각각 입력하고 테스트를 하면 의도대로 테스트가 통과하는 걸 볼 수 있었습니다
https://gmlwjd9405.github.io/2019/11/27/junit5-guide-parameterized-test.html
https://effortguy.tistory.com/117
https://junit.org/junit5/docs/current/user-guide/#writing-tests-display-name-generator
https://junit.org/junit5/docs/5.2.0/api/org/junit/jupiter/params/provider/Arguments.html
'테스트코드' 카테고리의 다른 글
| 외부로부터 의존하지 않는 테스트 ... OAuth 로그인 테스트도 할 수 있다! (WireMock) (0) | 2023.03.07 |
|---|