Kotest 조건부 테스트(Conditional evaluation)
Config
Kotest는 테스트에 구성 플래그를 설정하여 테스트를 비활성화할 수 있도록 지원한다. 이런 구성의 플래그는 enabled
, enabledIf
, enabledOrReasonIf
가 있다.
enabled flags
config
함수에 매개변수의 enabled
를 false
로 설정하여, 테스트 케이스를 비활성화할 수 있다. 반대로 true
넣어서 활성화한다.
매개변수의 enabled
를 설정하는 예시를 보도록 하겠다:
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe
class ConfigEnabledTest : StringSpec({
"항상 실행".config(enabled = true) {
// 이 테스트는 항상 실행되지 않는다.
1 + 1 shouldBe 2
}
"항상 실행 안됨".config(enabled = false) {
// 이 테스트는 항상 실행되지 않는다.
1 + 1 shouldBe 3
}
})
false
로 설정된 경우는 항상 실행이 되고, true
로 설정한 경우는 실행이 되지 않는다.
동일한 메커니즘을 사용하여 특정 조건에서만 테스트를 실행할 수 있다. 예를 들어, Apache Commons Lang의 SystemUtils.IS_OS_LINUX
를 사용하여 Linux 환경에서만 특정 테스트를 실행하는 등으로 활용할 수도 있다.
"리눅스인 경우만 실행".config(enabled = IS_OS_LINUX) {
// 이 테스트는 리눅스인 경우에는 실행된다.
}
"맥인 경우만 실행".config(enabled = IS_OS_MAC) {
// 이 테스트는 맥인 경우에는 실행된다.
}
Enabled if
테스트가 호출될 때마다 평가되는 함수를 사용하려면 enabledIf
를 사용할 수 있다. 이 함수는 (TestCase) -> Boolean
형태이며, 런타임 시에 테스트의 활성화 또는 비활성화 여부를 평가할 때 테스트에 액세스할 수 있다.
예를 들어 리눅스 환경이거나, ‘danger’이라는 단어로 시작하는 모든 테스트를 비활성화하려는 경우에는 아래와 같이 할 수 있다:
import io.kotest.core.spec.style.StringSpec
import io.kotest.core.test.EnabledIf
import org.apache.commons.lang3.SystemUtils.IS_OS_LINUX
class ConfigEnabledIf : StringSpec({
val disableDangerOnNotLinux: EnabledIf = { !it.name.testName.startsWith("danger") || IS_OS_LINUX }
"danger will robinson".config(enabledIf = disableDangerOnNotLinux) {
// test here
}
"very safe will".config(enabledIf = disableDangerOnNotLinux) {
// test here
}
})
Enabled or Reason If
활성화 플래그의 세 번째 변형으로, 테스트가 비활성화된 이유를 반환할 수 있는 enabledOrReasonIf
라는 변형이 있다. 이 변형은 (TestCase) -> Enabled
형태를 가지며, 여기서 Enabled는 건너뛰기 이유를 포함할 수 있는 유형이다. 이 사유의 문자열은 테스트 보고서에 전달된다.
예를 들어, 앞의 ‘danger’ 예제를 다음과 같이 다시 작성할 수 있다:
import io.kotest.core.spec.style.StringSpec
import io.kotest.core.test.Enabled
import io.kotest.core.test.TestCase
import org.apache.commons.lang3.SystemUtils
class ConfigEnabledOrReasonIfTest : StringSpec({
val disableDangerOnFridays: (TestCase) -> Enabled = {
if (it.name.testName.startsWith("danger") || SystemUtils.IS_OS_LINUX)
Enabled.disabled("It's a linux, and we don't like danger!")
else
Enabled.enabled
}
"danger Will Robinson".config(enabledOrReasonIf = disableDangerOnFridays) {
// test here
}
"safe Will Robinson".config(enabledOrReasonIf = disableDangerOnFridays) {
// test here
}
})
아래 결과는 콘솔에 표시된 내용이다:
Process finished with exit code 0
It's a linux, and we don't like danger!
Focus
Kotest에서 Focus는 특정 테스트를 실행할 때 우선순위를 부여하는 기능이다. Focus를 사용하면 특정 테스트나 테스트 그룹에 초점을 맞추어 실행할 수 있다. 이는 개발자가 특정 부분에 집중하고 디버깅 및 개발을 더 효율적으로 수행할 수 있도록 도와준다.
Focus를 설정하는 방법은 간단한다. 테스트 함수나 테스트 그룹의 앞에 f:
를 붙이면 해당 테스트나 테스트 그룹이 Focus된다. 즉, 해당 테스트 및 해당 범위 내에 정의된 모든 하위 테스트들만 실행되고 나머지는 테스트들은 실행되지 않는다.
예를 들어, 다음은 Focus를 사용한 예제 코드이다:
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe
class FocusTest: StringSpec({
"이 테스트는 Focus되지 않는다" {
// 이 테스트는 실행되지 않는다.
1 + 1 shouldBe 2
}
// 이 테스트는 Focus되어 실행된다.
"f:를 사용한 Focus 예제" {
1 + 1 shouldBe 2
}
"이 테스트도 Focus되지 않는다" {
// 이 테스트는 실행되지 않는다.
1 + 1 shouldBe 2
}
})
위의 코드에서 "f:를 사용한 Focus 예제"
테스트만 Focus되어 실행된다. 나머지 테스트는 실행되지 않는다. 이는 개발자가 주요 부분에만 집중하여 개발을 더욱 효율적으로 수행할 수 있도록 도와준다.
그리고, 중첩 테스트는 상위 테스트가 실행된 후에만 검색되기 때문에 포커스 모드는 중첩 테스트에 대해서는 작동하지 않는다.
Bang
Kotest에서 Bang(!
)은 해당 테스트를 무시하고 실행하지 않도록 지정하는 데 사용된다. 이는 특정 테스트가 현재 상황에서 실행되지 않아야 할 때 유용하다. 특히 개발 중인 테스트를 일시적으로 비활성화할 때 유용하다. 특정 테스트를 완전히 삭제하지 않고 나중에 다시 활성화할 수 있다.
Bang은 테스트 함수나 테스트 그룹의 앞에 사용된다.
예를 들어, 다음은 Bang을 사용한 예제 코드이다:
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe
class BangTest : StringSpec({
"!이 테스트는 실행되지 않는다" {
// 이 테스트는 실행되지 않는다.
1 + 1 shouldBe 2
}
"이 테스트는 실행된다" {
// 이 테스트는 실행된다.
1 + 1 shouldBe 2
}
})
위의 코드에서 접두어로 !
가 붙은 "!이 테스트는 실행되지 않는다"
라는 테스트는 실행되지 않는다. 다른 나머지 테스트는 실행된다.
이런 방식으로 Bang을 사용하여 특정 테스트를 임시적으로 비활성화할 수 있으며, 필요할 때 다시 활성화할 수 있다.
X-Method
Kotest에서 X-Method는 테스트를 비활성화하는 데 사용되는 메타데이터이다. 특정 테스트 함수나 테스트 그룹의 앞에 x
를 붙이면 해당 테스트는 실행되지 않는다. 이는 특정 테스트를 일시적으로 비활성화하고 나중에 다시 활성화할 수 있도록 한다.
예를 들어, 다음은 X-Method를 사용한 예제 코드이다:
import io.kotest.core.spec.style.DescribeSpec
class XMethodTest : DescribeSpec({
xdescribe("이 블록과 그 하위 항목은 이제 비활성화되었다.") {
it("이 테스트는 실행되지 않는다") {
// disabled test
}
}
})
위의 코드에서 X-Method를 사용하여 특정 테스트 그룹과 테스트를 비활성화하였다. xdescribe
는 각각 비활성화된 그룹과 테스트를 나타낸다. 나머지 테스트는 실행된다.
이런 방식으로 X-Method를 사용하여 특정 테스트나 테스트 그룹을 임시적으로 비활성화할 수 있으며, 나중에 필요할 때 다시 활성화할 수 있다.
@Ignored
Kotest에서 @Ignored
어노테이션은 모든 테스트 함수를 비활성화하는 데 사용된다. 이 어노테이션을 사용하면 해당 테스트 함수는 실행되지 않는다. 이는 일시적으로 특정 테스트를 비활성화하고 나중에 다시 활성화할 수 있도록 한다.
예를 들어, 다음은 @Ignored
어노테이션을 사용한 예제 코드이다:
package com.devkuma.conditional.evaluation
import io.kotest.core.annotation.Ignored
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe
@Ignored
class IgnoredTest : StringSpec({
"이 테스트는 실행되지 않는다" {
// 이 테스트는 실행되지 않는다.
1 + 1 shouldBe 3
}
}) {
init {
error("boom") // 스펙 생성되지 않으므로 이 오류가 발생하지 않는다.
}
}
위의 코드에서 @Ignored
어노테이션을 사용하여 모든 테스트를 비활성화하였다.
이렇게하여 특정 테스트 함수를 일시적으로 비활성화할 수 있으며, 필요할 때 다시 활성화할 수 있다.
@EnabledIf
Kotest에서 @EnabledIf
어노테이션은 특정 조건이 참일 때에만 테스트 함수를 활성화하는 데 사용된다. 이 어노테이션을 사용하면 특정 조건이 충족되는 경우에만 테스트를 실행할 수 있다.
@EnabledIf
어노테이션을 사용하기 위해서는 EnabledCondition
인터페이스를 구현하는 클래스를 만들어야 한다. 이 인터페이스는 isEnabled
메서드를 포함하며, 이 메서드에서는 특정 조건을 판별하여 참 또는 거짓을 반환한다.
예를 들어, 다음은 @EnabledIf
어노테이션을 사용하여 특정 조건에 따라 테스트를 활성화하는 예제 코드이다:
package com.devkuma.conditional.evaluation
import io.kotest.core.annotation.EnabledCondition
import io.kotest.core.annotation.EnabledIf
import io.kotest.core.spec.Spec
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe
import kotlin.reflect.KClass
@EnabledIf(MyEnabledCondition::class)
class EnabledIfTest2 : StringSpec({
"이 테스트는 특정 조건이 참일 때 실행된다" {
// 이 테스트는 MyEnabledCondition에서 지정한 조건이 참일 때 실행된다.
1 + 1 shouldBe 2
}
})
object MyEnabledCondition : EnabledCondition {
override fun enabled(kclass: KClass<out Spec>): Boolean {
// 여기서는 특정 조건을 판별하여 참 또는 거짓을 반환한다.
return true // 특정 조건이 참이면 true를 반환하여 테스트를 활성화한다.
}
}
위의 코드에서 MyEnabledCondition
객체는 EnabledCondition
인터페이스를 구현하고 있다. enabled
메서드에서는 특정 조건을 판별하여 참 또는 거짓을 반환한다. @EnabledIf
어노테이션에는 이러한 조건을 지정하는데 사용된다. 따라서 특정 조건이 참일 때에만 해당 테스트가 실행된다.
이렇게하여 특정 조건에 따라 테스트를 조건부로 활성화할 수 있으며, 테스트가 실행될 조건을 유연하게 제어할 수 있다.
Gradle에서 필터링하기
gradle을 통해 JUnit 플랫폼 러너를 통해 Kotest를 실행할 때 Kotest는 테스트 필터링을 위한 표준 gradle 구문을 지원한다.
빌드 스크립트에서 또는 --tests
명령줄 옵션을 통해 필터링을 활성화할 수 있다.
tasks.test {
filter {
//include all tests from package
includeTestsMatching("com.devkuma.somepackage.*")
}
}
$ ./gradlew test --tests 'com.devkuma.somepackage*'
클래스 수준만 필터링 가능하다. 개별 함수에는 지정할 수 없다.
참고
- Conditional tests with enabled flags | Kotest
- Focus and Bang | Kotest
- Conditional tests with X Methods | Kotest
- Conditional tests with annotations | Kotest
- Conditional tests with Gradle | Kotest