Kotest 격리 모드(Isolation Modes)
Isolation Modes
Isolation Modes의 설정을 어떻게 하냐에 따라 테스트 성능을 차이가 발생할 수 있고, 인스턴스 재사용으로 인한 테스트 실패도 방지할 있게 때문에 반듯이 알아두어야 한다.
Isolation Mode를 설정하는 방법은 3가지가 있다. IsolationMode라는 enum으로 제어할 수 있으며 InstancePerTest
, SingleInstance
, InstancePerLeaf
가 있다. 상황에 맞게 원하는 방식대로 사용하면 된다.
테스트 간에 공유되는 상태를 초기화할 수 있도록 테스트가 새 인스턴스 내에서 실행되도록 하려면 격리 모드를 변경하면 된다.
이 작업은 다음과 같은 DSL을 사용하여 isolationMode
에 값을 할당하여 수행할 수 있다:
class MyTest : WordSpec({
isolationMode = IsolationMode.SingleInstance
// tests here
})
또는 fun isolationMode(): IsolationMode
함수를 오버라이드 설정할 수 있다:
class MyTest : WordSpec() {
override fun isolationMode() = IsolationMode.SingleInstance
init {
// tests here
}
}
DANGER
Kotest의 기본값은 단일 인스턴스로, 이 프레임워크의 모티브가 된 ScalaTest와 Jest, Jasmine 및 기타 자바스크립트 프레임워크와 동일하지만 JUnit과는 다르다.SingleInstance
디폴트 격리 모드인 SingleInstance
은 Spec 클래스의 하나의 인스턴스가 생성된 다음
모든 테스트가 완료될 때까지 각 테스트 케이스가 차례로 실행되는 방식이다.
이 모드는 모든 테스트 간의 상태 공유를 허용하므로 테스트 간의 의존성을 유지하고자 할 때 유용하다.
package com.devkuma.kotest.tutorial.isolation
import io.kotest.core.spec.style.WordSpec
import java.util.*
class SingleInstanceExample : WordSpec({
val id = UUID.randomUUID()
"a" should {
println("a: $id")
"b" {
println("b: $id")
}
"c" {
println("c: $id")
}
}
})
다음은 예제를 실행한 결과이다:
a: 3823310d-43d3-47a0-953b-fa3afeb39307
b: 3823310d-43d3-47a0-953b-fa3afeb39307
c: 3823310d-43d3-47a0-953b-fa3afeb39307
실행 결과는 모든 테스트에 동일한 인스턴스가 사용되므로 동일한 ID가 세 번 출력된다.
InstancePerTest
다음 IsolationMode.InstancePerTest
모드는 내부 콘텍스트를 포함하여 모든 테스트 케이스에 대해 새 Spec이 생성된다.
즉, 외부 콘텍스트는 Spec의 자체 인스턴스에서 “독립 실행형(stand alone)” 테스트로 실행된다.
예제를 통해 이를 명확히 알 수 있다.
package com.devkuma.kotest.tutorial.isolation
import io.kotest.core.spec.IsolationMode
import io.kotest.core.spec.style.WordSpec
import java.util.*
class InstancePerTestExample : WordSpec() {
override fun isolationMode(): IsolationMode = IsolationMode.InstancePerTest
val id = UUID.randomUUID()
init {
"a" should {
println("a: $id")
"b" {
println("b: $id")
}
"c" {
println("c: $id")
}
}
}
}
다음은 예제를 실행한 결과이다:
a: 19c3b379-a688-428c-b3e8-8cb507bdf083
a: ffaff5f6-5c6a-41a9-98b9-52f9ca134dfa
b: ffaff5f6-5c6a-41a9-98b9-52f9ca134dfa
a: 08e42544-def7-4859-8b2b-34bb50fe83b0
c: 08e42544-def7-4859-8b2b-34bb50fe83b0
외부 콘텍스트(테스트 “a”)가 먼저 실행되고, 그런 다음(테스트 “b”)에 대해 다시 실행되고, (테스트 “c”)에 대해 다시 실행된다. Spec 클래스의 깨끗한 인스턴스에서 매번, 변수를 재사용하고자 할 때 매우 유용하다.
InstancePerLeaf
IsolationMode.InstancePerLeaf
모드는 내부 컨텍스트를 포함해서 모든 테스트 케이스에 대해 새로운 인스턴스를 생성하여 독립적으로 실행한다. 이 모드는 테스트 케이스 간의 상태 공유를 방지하여 테스트의 독립성을 보장한다. 그러나 그만큼 자원을 많이 소모하는 점을 염두해 두고 이 모드를 사용해야 한다.
예제를 통해 이를 확인하도록 한다.
package com.devkuma.kotest.tutorial.isolation
import io.kotest.core.spec.IsolationMode
import io.kotest.core.spec.style.WordSpec
import java.util.*
class InstancePerLeafExample : WordSpec() {
override fun isolationMode(): IsolationMode = IsolationMode.InstancePerLeaf
private val id = UUID.randomUUID()
init {
"a" should {
println("a: $id")
"b" {
println("b: $id")
}
"c" {
println("c: $id")
}
}
}
}
다음은 예제를 실행한 결과이다:
a: 71830c57-6ee0-4b1f-8c32-812defac2b1e
b: 71830c57-6ee0-4b1f-8c32-812defac2b1e
a: 480ee65a-df4c-4a78-ac80-b6ae2c85ee20
c: 480ee65a-df4c-4a78-ac80-b6ae2c85ee20
“a” 테스트가 먼저 실행되고 동일한 인스턴스에서 “b” 테스트가 실행된다. 그런 다음 새 Spec이 생성되고 테스트 “a"가 다시 실행된 다음 테스트 “c"가 실행된다.
Global Isolation Mode
시스템 속성을 통해 전역적으로 Isolation Mode를 설정할 수도 있다.
object GlobalIsolationConfiguration : AbstractProjectConfig() {
override val isolationMode = IsolationMode.SingleInstance
}