Kotest 테스트 컨테이너(Testcontainers) 확장

Testcontainers는 테스트 시에 컨테이너 기반의 외부 리소스를 사용할 수 있게 해주는 도구이다. 이를 통해 실제 환경과 유사한 테스트 환경을 구축하고, 외부 리소스에 대한 테스트를 보다 쉽게 수행할 수 있다. 여기서는 Kotest에서 Testcontainers를 활용하는 방법에 대해서 설명한다.

Testcontainers

Testcontainers는 독립적이고 재사용 가능한 테스트 환경을 구축하기 위한 도구이다. 이는 컨테이너 기반의 테스트를 지원하여, 로컬 머신에서 실행되는 테스트 환경과 동일한 환경을 프로그래밍 방식으로 구축할 수 있다. Kotest는 Testcontainers와 함께 사용될 수 있어, 테스트에 필요한 외부 리소스를 관리하고, 이를 통해 더 견고하고 신뢰할 수 있는 테스트를 작성할 수 있다.

Testcontainers를 사용하는 주요 장점은 다음과 같다:

  1. 일관된 환경: 각 테스트가 실행될 때마다 일관된 환경을 제공하여 테스트 결과를 예측할 수 있다.
  2. 독립성: 외부 리소스를 컨테이너화하여, 테스트가 서로 영향을 미치지 않도록 보장한다.
  3. 테스트 환경 구축의 용이성: 코드로 테스트 환경을 프로그래밍 방식으로 구축하고 관리할 수 있다.
  4. 다양한 컨테이너 지원: 다양한 종류의 컨테이너(예: Docker, Kubernetes)를 지원하여, 다양한 테스트 시나리오를 구축할 수 있다.

Testcontainers 프로젝트는 테스트 내부에서 사용하기에 이상적인 일반적인 데이터베이스, elasticsearch, kafka, Selenium 웹 브라우저 또는 기타 Docker 컨테이너에서 실행할 수 있는 모든 것의 경량 임시 인스턴스를 제공한다.

Kotest는 데이터베이스 및 kafka를 위한 특수 확장 및 지원되는 모든 도커 이미지에 대한 일반 컨테이너 지원 등 여러 확장 기능을 제공하는 추가 모듈을 통해 Testcontainers와의 통합을 제공한다.

의존성 추가

사용하려면 Gradle 빌드 파일에 다음 종속성을 추가해야 한다.

dependencies {
    testImplementation("io.kotest.extensions:kotest-extensions-testcontainers:${kotestVersion}")
}

참고: io.kotest.extensions의 Gropu ID는 기본 kotest(io.kotest)과는 다르다.

Maven 프로젝트의 경우에는 다음과 같이 의존성을 추가한다:

<dependency>
    <groupId>io.kotest.extensions</groupId>
    <artifactId>kotest-extensions-testcontainers</artifactId>
    <version>${kotest.version}</version>
    <scope>test</scope>
</dependency>

Databases

Kotest에서 Testcontainers를 사용하는 방법은 간단한다. 테스트 코드 내에서 Testcontainers 라이브러리를 사용하여 필요한 컨테이너를 시작하고, 테스트를 실행한 후에 컨테이너를 정리하면 된다.

예를 들어, 데이터베이스 연동 테스트를 수행하는 경우, 테스트 시작 시에 데이터베이스 컨테이너를 시작하고, 테스트 종료 시에 컨테이너를 중지하는 것이 일반적이다.

이를 위해 Kotest에서는 beforeTestafterTest를 사용하여 테스트 실행 전/후에 필요한 작업을 수행할 수 있다.

아래는 Kotest와 Testcontainers를 함께 사용하는 예시 코드이다:

import io.kotest.core.spec.style.FreeSpec
import org.testcontainers.containers.PostgreSQLContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers

@Testcontainers
class PostgreSqlTest : FreeSpec() {

    companion object {
        @Container
        val postgresContainer: PostgreSQLContainer<Nothing> = PostgreSQLContainer<Nothing>()
            .withDatabaseName("test")
            .withUsername("test")
            .withPassword("test")
            .withExposedPorts(5432)
    }

    override fun beforeTest(testCase: TestCase) {
        postgresContainer.start()
        System.setProperty("DB_URL", postgresContainer.jdbcUrl)
        System.setProperty("DB_USERNAME", postgresContainer.username)
        System.setProperty("DB_PASSWORD", postgresContainer.password)
    }

    override fun afterTest(testCase: TestCase, result: TestResult) {
        postgresContainer.stop()
    }

    init {
        "Database test" {
            // 데이터베이스 테스트 코드 작성
        }
    }
}

위 코드에서는 PostgreSQL 컨테이너를 사용하여 데이터베이스 테스트를 수행한다. @Testcontainers 어노테이션을 사용하여 Testcontainers를 활성화하고, @Container 어노테이션을 사용하여 컨테이너를 정의한다. 그리고 beforeTestafterTest를 오버라이드하여 테스트 실행 전/후에 컨테이너를 시작하고 중지한다.


참조




최종 수정 : 2024-04-21