Kotest 소프트 단어문(Soft Assertions)

Soft Assertions는 assertSoftly 함수를 이용하여 여러 단언문을 묶어서 수행하기 위한 용도로 사용한다.

Soft Assertions

일반적으로 shouldBe와 같은 단언문은 실패하면 바로 예외를 던진다. 그렇게 되면, 나중에 위치한 단언문은 결과를 볼 수 없게 된다. 그러나 때로는 테스트에서 여러 단언문을 수행하고 실패한 모든 단언문을 보고 싶을 때가 있다. Kotest는 이를 위해 assertSoftly 함수를 제공한다.

assertSoftly {
    foo shouldBe bar
    foo should contain(baz)
}

단순히 shouldBe와 같은 Matcher를 여러번 수행함으로써 다수의 단언을 수행할 수 있지만 이런 경우 앞선 단언이 실패하는 경우 후속 단언을 수행하지 않고 테스트가 멈추기 때문에 후속 단언의 성공여부를 앞선 단언이 성공하기 전까지 판단하기 어렵다.

assertSoftly를 사용하면, 하나의 Assertion이 실패하더라도 그룹 내의 나머지 Assertion이 실행되며 테스트가 계속 진행된다. 즉, assertSoftly는 모든 Assertion을 실행하고 결과를 모으는 방식으로 동작한다. 참고로, JUnit의 assertAll과 동일하게 동작한다.

assertSoftly는 주로 여러 부분의 동작을 동시에 테스트하거나, 특정 상태를 검증할 때 유용한다. 실패한 Assertion의 위치를 정확히 파악하고자 할 때도 유용하게 사용될 수 있다.  예를 들면, 데이터 검증시에 equals로 객체의 프로퍼티들을 검증할 때 주로 사용하면 유용하다.

assertSoftly를 사용하게 되면 블록 내부의 단언문이 실패하도 테스트는 계속 실행된다. 모든 실패는 블록이 끝나고 나서 단일 예외로 보고된다.

또 다른 버전의 assertSoftly는 테스트 대상과 테스트 대상을 수신자로 하는 람다를 사용한다.

assertSoftly(foo) {
    shouldNotEndWith("b")
    length shouldBe 3
}

다음은 assertSoftly의 간단한 사용 예제이다:

package com.devkuma.kotest.tutorial.assertions

import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe
import io.kotest.assertions.assertSoftly

class SoftAssertionTest : StringSpec({

    "assertSoftly를 사용한 테스트" {
        val person = Person(
            "devkuma",
            30
        )

        assertSoftly {
            person.name shouldBe "devkuma"
            person.age shouldBe 30
        }
    }
})

data class Person(
    val name: String,
    val age: Int
)

위의 코드에서는 assertSoftly 블록 내에서 여러 Assertion을 그룹화하여 실행하고 있다. 만약 하나의 Assertion이 실패하더라도, 나머지 Assertion은 여전히 실행되며 테스트가 중단되지 않는다. 이렇게 함으로써 한 번에 여러 가지 조건을 동시에 테스트할 수 있다.

프로젝트 구성을 통해 모든 테스트에 암묵적으로 단언문이 추가되도록 소프트하게 구성할 수 있다.


참조




최종 수정 : 2024-04-14