Kotest 테스트 순서 제어(Ordering)
테스트 순서 제어
Kotest는 다양한 방법으로 테스트 순서를 제어할 수 있다. Ordering 기능을 사용하여 테스트를 조절함으로써, 테스트 간의 의존성이나 상호작용에 따른 문제를 방지하고, 보다 예측 가능한 테스트 실행 환경을 구성할 수 있다.
Kotest에서 Ordering을 제어하는 방법은 크게 두 가지이다:
- Spec Ordering: 특정 테스트 스펙(또는 테스트 클래스) 내부에서 테스트의 실행 순서를 조절하는 방법이다. 이를 통해 특정 스펙 내의 테스트들의 실행 순서를 조절할 수 있다.
- Test Ordering: 특정 테스트 스펙 내의 테스트들 또는 특정 테스트 스펙들 간의 실행 순서를 조절하는 방법이다. 이를 통해 여러 개의 테스트 스펙 간의 실행 순서를 조절할 수 있다.
Spec Ordering
기본적으로 스펙 클래스의 순서는 정의되어 있지 않다. 즉, 검색 메커니즘이 어떤 순서로 찾든 기본적으로 무작위이다.
순서가 없어도 크게 지장은 없지만, 스펙상 실행 순서를 제어야 해야 해야 한다면, 프로젝트 구성에서 순서를 지정하면 된다.
class OrderingConfig: AbstractProjectConfig() {
override val specExecutionOrder = SpecExecutionOrder.Undefined
}
SpecExecutionOrder
에는 몇 가지 옵션이 있다:
Undefined
: 기본값이다. 순서가 정의되지 않으며, 런타임에 발견되는 순서대로 실행된다. 예를 들어 JVM 클래스 경로 검색 또는 자바스크립트 파일에 표시된 순서대로 실행된다.Lexicographic
: 사전순으로 정렬된다.Random
: 명시적으로 임의의 순서로 사양이 실행된다.Annotated
: 클래스에 추가된@Order
어노테이션을 사용하여 입력된 값에 가장 낮은 값부터 먼저 실행된다. 이 어노테이션이 없으면 “마지막"으로 간주된다. 이 옵션은 JVM에서만 작동한다. 동일한 값은 임의로 실행된다.
Lexicographic으로 순서 지정
다음 예제는 사전순으로 실행되도록 정의되어 있다.
package com.devkuma.kotest.tutorial.ordering
import io.kotest.core.config.AbstractProjectConfig
import io.kotest.core.spec.SpecExecutionOrder
import io.kotest.core.spec.style.FunSpec
class LexicographicConfig: AbstractProjectConfig() {
override val specExecutionOrder = SpecExecutionOrder.Lexicographic
}
class AlphaTest : FunSpec({
test("alpha") {
println("AlphaTest")
}
})
class BetaTest : FunSpec({
test("beta") {
println("BetaTest")
}
})
class GammaTest : FunSpec({
test("gamma") {
println("GammaTest")
}
})
class DeltaTest : FunSpec({
test("delta") {
println("DeltaTest")
}
})
테스트가 실행하면 아래와 같이 출력된다:
AlphaTest
BetaTest
DeltaTest
GammaTest
알파벳 순서인 AlphaTest
, BetaTest
, DeltaTest
, GammaTest
으로 출력이 된것을 확인할 수 있다.
Annotated으로 순서 지정
다음 예제는 @Order
로 어노테이션이 지정되었다.
package com.devkuma.kotest.tutorial.ordering
import io.kotest.core.config.AbstractProjectConfig
import io.kotest.core.spec.Order
import io.kotest.core.spec.SpecExecutionOrder
import io.kotest.core.spec.style.FunSpec
class AnnotatedConfig: AbstractProjectConfig() {
override val specExecutionOrder = SpecExecutionOrder.Annotated
}
@Order(1)
class FooTest : FunSpec({
test("foo") {
println("FooTest")
}
})
@Order(0)
class BarTest: FunSpec({
test("bar") {
println("BarTest")
}
})
@Order(1)
class FarTest : FunSpec({
test("far") {
println("FarTest")
}
})
class BooTest : FunSpec({
test("boo") {
println("BooTest")
}
})
테스트가 실행하면 아래와 같이 출력된다:
BarTest
FarTest
FooTest
BooTest
Order가 가장 낮은 BarTest
가 먼저 실행된다. FarTest
와 FooTest
는 그 다음으로 낮은 값을 이므로 그 다음에 실행되는데, 값이 모두 1이므로 그 사이의 순서는 정의되지 않는다. 마지막으로 BooTest
는 어노테이션이 없으므로 마지막으로 실행된다.
Test Ordering
스펙에 따라 여러 테스트를 실행할 때 실행하는 방법에는 일정한 순서가 있다.
기본적으로 순차적(sequential) 순서(테스트가 스펙에 정의된 순서)가 사용되지만 임의의(random) 순서 또는 사전적(lexicographic) 순서로 실행되도록 구성할 수도 있다.
이 설정은 Spec
또는 ProjectConfig
에서 testCaseOrder
함수를 재정의하여 구성할 수 있다. 둘 다 존재하는 경우 Spec의 설정이 우선권을 갖는다.
NOTE
중첩된 테스트는 테스트 순서 설정에 관계없이 항상 검색 순서(순차)로 실행된다.순차적(Sequential) 순서
아래 예제는 테스트는 랜덤 정의된 순서대로 실행된다:
package com.devkuma.kotest.tutorial.ordering.testordering
import io.kotest.core.spec.style.StringSpec
import io.kotest.core.test.TestCaseOrder
class SequentialSpecTest : StringSpec() {
override fun testCaseOrder(): TestCaseOrder = TestCaseOrder.Sequential
init {
"foo" {
// I run first as I'm defined first
println("foo")
}
"bar" {
// I run second as I'm defined second
println("bar")
}
}
}
랜덤(Random) 순서
아래 예제는 테스트는 랜덤 순서로 실행된다:
package com.devkuma.kotest.tutorial.ordering.testordering
import io.kotest.core.spec.style.StringSpec
import io.kotest.core.test.TestCaseOrder
class RandomSpecTest : StringSpec() {
override fun testCaseOrder(): TestCaseOrder = TestCaseOrder.Random
init {
"foo" {
// This test may run first or second
println("foo")
}
"bar" {
// This test may run first or second
println("bar")
}
}
}
테스트가 실행하면 아래와 같이 출력된다:
foo
bar
또는 아래와 같이 출력되기도 한다.
bar
foo
사전적(Lexicographic) 순서
아래 예제는 테스트는 사전적 순서로 실행된다:
package com.devkuma.kotest.tutorial.ordering.testordering
import io.kotest.core.spec.style.StringSpec
import io.kotest.core.test.TestCaseOrder
class LexicographicSpecTest : StringSpec() {
override fun testCaseOrder(): TestCaseOrder = TestCaseOrder.Lexicographic
init {
"beta" {
// I run second as gamma < beta < alpha
println("beta")
}
"alpha" {
// I run first as gamma < beta < alpha
println("alpha")
}
"gamma" {
// I run third as gamma < beta < alpha
println("gamma")
}
}
}
테스트가 실행하면 아래와 같이 출력된다:
alpha
beta
gamma