Kotest 테스트 순서 제어(Ordering)

Kotest에서의 Ordering은 테스트 실행의 순서를 제어하는 기능이다. 특정한 순서로 테스트를 실행하고 싶거나, 특정 조건에 따라 테스트를 필터링하고 실행할 때 유용하다.

테스트 순서 제어

Kotest는 다양한 방법으로 테스트 순서를 제어할 수 있다. Ordering 기능을 사용하여 테스트를 조절함으로써, 테스트 간의 의존성이나 상호작용에 따른 문제를 방지하고, 보다 예측 가능한 테스트 실행 환경을 구성할 수 있다.

Kotest에서 Ordering을 제어하는 방법은 크게 두 가지이다:

  1. Spec Ordering: 특정 테스트 스펙(또는 테스트 클래스) 내부에서 테스트의 실행 순서를 조절하는 방법이다. 이를 통해 특정 스펙 내의 테스트들의 실행 순서를 조절할 수 있다.
  2. 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가 먼저 실행된다. FarTestFooTest는 그 다음으로 낮은 값을 이므로 그 다음에 실행되는데, 값이 모두 1이므로 그 사이의 순서는 정의되지 않는다. 마지막으로 BooTest는 어노테이션이 없으므로 마지막으로 실행된다.

Test Ordering

스펙에 따라 여러 테스트를 실행할 때 실행하는 방법에는 일정한 순서가 있다.

기본적으로 순차적(sequential) 순서(테스트가 스펙에 정의된 순서)가 사용되지만 임의의(random) 순서 또는 사전적(lexicographic) 순서로 실행되도록 구성할 수도 있다.

이 설정은 Spec 또는 ProjectConfig에서 testCaseOrder 함수를 재정의하여 구성할 수 있다. 둘 다 존재하는 경우 Spec의 설정이 우선권을 갖는다.

순차적(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

참조




최종 수정 : 2024-04-23