(Kotest 5.9.x 버전 기준의 내용입니다)
Kotest는 병렬 처리를 위한 parallelism 값이나 extension과 같은 설정을 AbstractProjectConfig class를 통해 할 수 있다.
import io.kotest.core.config.AbstractProjectConfig
object MyKotestProjectConfig : AbstractProjectConfig() {
override val parallelism = 3
}
https://kotest.io/docs/framework/project-config.html
Project Level Config | Kotest
Kotest is flexible and has many ways to configure tests, such as configuring the order of tests inside a spec, or how
kotest.io
그리고 테스트에 대해 Lifecycle listener를 전역으로 적용할 수 있는데 이때 @AutoScan을 사용하기도 한다.
import io.kotest.core.annotation.AutoScan
import io.kotest.core.listeners.AfterProjectListener
import io.kotest.core.listeners.BeforeProjectListener
@AutoScan
object MyProjectListener : BeforeProjectListener, AfterProjectListener {
override suspend fun beforeProject() {
println("Project starting")
}
override suspend fun afterProject() {
println("Project complete")
}
}
https://kotest.io/docs/framework/extensions/extensions-introduction.html#how-to-use
Introduction to Extensions | Kotest
Extensions are reusable lifecycle hooks. In fact, lifecycle hooks are themselves represented internally as instances
kotest.io
기본적으로 이러한 설정 클래스는 따로 path를 지정하지 않아도 적용되는데,
이는 Kotest가 테스트를 실행하면서 해당 클래스가 있는지 scan을 하기 때문이다.
하지만 테스트 실행 시에 매번 설정을 scan 하기 때문에 설정 클래스 파일만 잘 관리하면 되지만 이로인해서 테스트 실행 시간이 늘어날 수 있다.
또한 테스트를 실행하면 다음과 같이 Warning 로그가 뜨는 것을 볼 수 있다.
컴퓨팅 파워가 넉넉한 로컬 개발 환경에서는 테스트 시간이 늘어나봤자 경험적으로 ~10초 정도이지만
그렇지 못한 CI 환경(특히 기본 Github Actions 컴퓨팅 환경)에서는 분단위로 테스트 시간이 늘어나게되어 개발 cycle이 조금씩 지연되는 원인이 되기도 한다.
실제로 나의 경우 CI 환경에서 설정 @AutoScan 달린 설정 scan으로 인해 1분 정도의 시간이 소모되었다.
이번 포스팅에서는 설정을 scan하는 runtime detection 설정을 변경하여 테스트 실행 시간을 개선하고 그 과정에서의 트러블 슈팅 경험을 정리하도록 한다.
테스트 실행 시 설정을 scan하는 runtime detection을 끄는 설정은 아래와 같고 기본적으로 모두 false 상태이다. (5.9.x 버전 기준)
- kotest.framework.classpath.scanning.config.disable
- kotest.framework.classpath.scanning.autoscan.disable
이 설정을 모두 true로 하고자한다면 src/test/resources 경로에 kotest.properties 파일을 생성하여 설정을 추가해주면된다.
kotest.framework.classpath.scanning.config.disable=true
kotest.framework.classpath.scanning.autoscan.disable=true
설정에 따른 테스트 실행 시간을 확인하기 위해 나의 CI 환경에서 옵션을 추가해가면서 확인을 해보았다.
그 결과는 아래와 같다.
trial | default config | scanning.autoscan.disable=true | scanning.config.disable=true scanning.autoscan.disable=true |
1st | 3m 34s | 2m 54s | 2m 18s |
2nd | 3m 24s | 2m 56s | 2m 17s |
3rd | 3m 21s | 2m 51s | 2m 18s |
runtime detection 설정을 끄니 로컬에서는 수 초의 차이밖에 보이지 않았지만,
CI 환경에서는 1분 이상의 드라마틱한 개선이 이뤄지는 것을 확인할 수 있었다.
하지만 Spring framework를 사용할 때 통합 테스트를 위해 Kotest Spring extension을 사용하고
Spec class의 생성자에 Spring bean을 주입받아서 사용한다면 위 설정을 했을 때 오류가 날 수 있다.
io.kotest.engine.spec.SpecInstantiationException: Could not create instance of class xx.XXTest. Specs must have a public zero-arg constructor.
이는 runtime detection 기능을 모두 껐기 때문에 생기는 문제로 document에도 설명하고 있다.
그렇기 때문에 추가적으로 AbstractProjectConfig 구현체를 만들어 Spring과 관련된 extension을 등록해줘야한다.
import io.kotest.core.config.AbstractProjectConfig
import io.kotest.core.extensions.Extension
import io.kotest.extensions.spring.SpringAutowireConstructorExtension
import io.kotest.extensions.spring.SpringExtension
object KotestProjectConfiguration : AbstractProjectConfig() {
override fun extensions(): List<Extension> {
return listOf(
SpringExtension, // Integrate Spring with Kotest
SpringAutowireConstructorExtension, // Allow Spring bean constructor injection for Kotest Spec classes
)
}
}
그리고 해당 설정을 kotest.proprerties에서 사용하도록 추가해줘야 정상적으로 위 AbstractProjectConfig 구현체가 설정으로써 등록이 된다.
kotest.framework.classpath.scanning.config.disable=true
kotest.framework.classpath.scanning.autoscan.disable=true
kotest.framework.config.fqn=path.to.KotestProjectConfiguration
이렇게 설정을 해주면 Kotest Spec class에서 Spring bean을 주입할 수 있게된다.
'Java & Kotlin > Kotlin' 카테고리의 다른 글
Kotlin + Spring MVC 사용 시 요청 List 필드에 null이 들어가는 경우 (0) | 2025.03.03 |
---|---|
reified를 통해 generic type 정보 가져오기 (0) | 2023.01.16 |
[MockK] mock 객체가 호출되지 않았음을 검증하기 (1) | 2022.10.21 |
JPA entity의 VO로 Kotlin value class 사용하기 (3) | 2022.06.01 |
[MockK] 메서드 호출 순서 검증하기 (0) | 2022.04.15 |
댓글