본문 바로가기
개인 공부/Java, Python

[Java] @ParameterizedTest 써보기

by syLim___ 2024. 7. 20.
728x90

 

✅ ParameterizedTest

오늘 자바 공부를 하면서 간단한 문자열 계산기를 구현해봤다.

그리고 친구한테 코드 리뷰 좀 해달라고 했는데

친구가 테스트코드 짤 때 @ParameterizedTest 써서 해보라고 했다

 

그동안 다른 사람들이 @ParameterizedTest 어노테이션을 사용해서 짠 코드를 보기만 했지

내가 써본 적은 없었어서, 이번 기회에 써보기로 했따

 


✅ 의존성 추가

@ParameterizedTest를 사용하기 위해  maven 의존성을 추가해주고,

<dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-params</artifactId>
      <scope>test</scope>
</dependency>

 

아래 글을 통해서 사용법을 공부했다.

https://velog.io/@ohzzi/junit5-parameterizedtest

 

https://www.baeldung.com/parameterized-tests-junit-5


 

🐥 기존에 내가 구현했던 코드 (일부)

 

🐥 친구가 이런식으로 바꿔보라고 작성해준 코드

 

 

🐥 내가 수정한 테스트 코드

class StringCalculatorTest {

    private StringCalculator stringCalculator;

    @BeforeEach
    public void setup() {
        stringCalculator = new StringCalculator();
    }

    @ParameterizedTest
    @NullAndEmptySource
    @DisplayName("파라미터가 빈 문자열이나 null이면 0을 리턴")
    void returnZero(String input) {
        assertEquals(0, stringCalculator.calculate(input));
    }

    private static Stream<Arguments> singleNumber() {
        return Stream.of(
                Arguments.of("12345", 12345),
                Arguments.of("9999", 9999)
        );
    }
    @ParameterizedTest
    @MethodSource
    @DisplayName("파라미터로 숫자 하나만 주어질 경우 해당 숫자를 리턴")
    void singleNumber(String input, int expected) {
        assertEquals(expected, stringCalculator.calculate(input));
    }

    private static Stream<Arguments> defaultDelimiters() {
        return Stream.of(
                Arguments.of("1,2,3:4", 10),
                Arguments.of("  1  :2, 3:10", 16)
        );
    }
    @ParameterizedTest
    @MethodSource
    @DisplayName("기본 구분자 , : 로 구분")
    void defaultDelimiters(String input, int expected) {
        assertEquals(expected, stringCalculator.calculate(input));
    }

    private static Stream<Arguments> customDelimiters() {
        return Stream.of(
                Arguments.of("1//?\n2", 3),
                Arguments.of("3//~\n4", 7),
                Arguments.of("1:2//a\n3,4//?\n5", 15),
                Arguments.of("12//-\n2", 14),
                Arguments.of("1//+\n", 1)
        );
    }
    @ParameterizedTest
    @MethodSource
    @DisplayName("커스텀 구분자로 구분")
    void customDelimiters(String input, int expected) {
        assertEquals(expected, stringCalculator.calculate(input));
    }

    @ParameterizedTest
    @ValueSource(strings = {"-1,2", "1:-58", "1,-2//a\n3"})
    @DisplayName("파라미터 음수면 예외처리")
    void negaitveNumber(String input) {
        assertThrows(IllegalArgumentException.class, () -> stringCalculator.calculate(input));
    }

    @ParameterizedTest
    @ValueSource(strings = {"a:1", "1,,2"})
    @DisplayName("잘못된 형식이면 예외 처리")
    void wrongFormat(String input) {
        assertThrows(IllegalArgumentException.class, () -> stringCalculator.calculate(input));
    }

}

 


 

🐥 @CsvSource를 쓰지 않은 이유

내가 구현한 메서드의 리턴 타입이 String이 아니라 int였기 때문에

@CsvSource를 사용하면 int로의 타입 변환 과정이 추가로 필요해서

지저분하고 번거로웠다.

 

그래서 @MethodSource를 사용하였다.

 

🐥 @ValueSource를 쓴 이유

특정 문자열을 인풋으로 넣으면 예외를 던지는지 확인하기 위한 테스트는

파라미터가 하나만 필요하기 때문이다.

즉 , 각 input 문자열에 대한 예상 output은 지정해주지 않아도 되기 때문이다.

 


테스트 결과도 훨씬 깔끔해보인다!

 

 

728x90

'개인 공부 > Java, Python' 카테고리의 다른 글

[JAVA] SwingUtilities.invokeLater()  (2) 2024.10.09
[JAVA] Cloneable과 Objects.clone() / Shallow Copy에 대해서  (0) 2024.08.05
[Java] String 클래스  (0) 2024.07.02
[Java] 동일성, 동등성  (0) 2024.06.26
[Java] Reflection  (0) 2023.11.17