목차

개발 노트/Android

[테스트] JUnit5의 ParameterizedTest

천만일 2023. 10. 29. 04:44

안녕하세요.

오늘은 junit5의 ParameterizedTest에 대해 알아보겠습니다.

 

 

다음은 문자열로 입력받은 수식을 계산해서 출력해 주는 계산기에 대한 테스트입니다.

@Test
fun testCalculateAddExpression() {
    val outputStream = ByteArrayOutputStream()

        Calculator("10 + 2".byteInputStream(), outputStream).run()

    assertEquals(String(outputStream.toByteArray()), "12")
}

@Test
fun testCalculateSubtractExpression() {
    val outputStream = ByteArrayOutputStream()

        Calculator("10 - 2".byteInputStream(), outputStream).run()

    assertEquals(String(outputStream.toByteArray()), "8")
}

 

해당 테스트를 작성하며 마음에 걸렸던 부분은 다음과 같습니다.

  • 하나의 테스트가 하나의 인풋만 받을 수 있다는 점
  • 잇풋과 아웃풋이 테스트 코드의 일부로 작성되어 있어 가독성이 떨어지는 점
  • 계산기는 공개 메서드로 run()만 가지고 있음에도 input은 내부 로직을 다 아는 듯 덧셈, 뺄셈, 곱셈, 나눗셈으로 나뉘어 있다는 점

 

 

코드 리뷰를 통해 junit5의 @ParameterizedTest라는 기능이 해결해 줄 수 있다는 것을 알게 되었습니다.

 

Parameterized tests make it possible to run a test multiple times with different arguments.

 

@ParameterizedTest는 다른 인자를 통해 테스트를 여러 번 실행할 수 있도록 도와주는 기능입니다.

 

In addition, you must declare at least one source that will provide the arguments for each invocation and then consume the arguments in the test method.

 

@ParameterizedTest는 테스트 함수의 인자로 사용할 값을 선언하는 Source annotation과 같이 사용해야 합니다.

 

 

Source annotaion의 종류에는 다음과 같은 것들이 있습니다.

  • @ValueSource
  • @NullSource
  • @EmptySource
  • @NullAndEmptySource
  • @EnumSource
  • @MethodSource
  • @CsvSource
  • 등등..

ValueSource

@ParameterizedTest@ValueSource를 이용해서 위 테스트를 개선해 보겠습니다.

@ParameterizedTest
@ValueSource(strings = ["20 + 30"])
fun testCalculateAddExpression(expression: String) {
    val outputStream = ByteArrayOutputStream()

        Calculator(expression.byteInputStream(), outputStream).run()

    assertEquals(String(outputStream.toByteArray()), "50")
}

제가 테스트하고자 했던 인풋을 다음과 같은 형태로 추가해 두었습니다.

@ValueSource(strings = ["20 + 30"])

 

CsvSource

여기서 발생한 문제는 여러 개의 인풋을 테스트하려면 여러 인풋에 대응되는 기대 아웃풋도 설정해주어야 한다는 점이었습니다.

이때 사용할 수 있는 것이 @CsvSource입니다.

 

@CsvSource는 쉼표를 기준으로 문자열을 해석하는 csv 포맷에 맞춘 Source입니다.

이를 활용하여 다음과 같이 개선했습니다.

@ParameterizedTest
@CsvSource(
    value = [
        "10 + 2, 12",
        "10 - 2, 8",
        "10 / 2, 5",
        "10 * 2, 20",
    ]
)
fun testCalculate(expression: String, expected: String) {
      val outputStream = ByteArrayOutputStream()

        Calculator(expression.byteInputStream(), outputStream).run()

        assertEquals(String(outputStream.toByteArray()), expected)
}

@CsvSource를 통해 내부 로직인 덧셈, 뺄셈 등을 테스트 코드에서 배제할 수 있게 되었습니다.

 

 


참고