Kotlin/JS에서 테스트 실행하기
Kotlin/JS에서 테스트 실행하기
Kotlin Multiplatform Gradle 플러그인을 사용하면 Gradle 구성으로 지정할 수 있는 다양한 테스트 러너를 통해 테스트를 실행할 수 있어요.
Kotlin/JS에서 테스트를 실행하는 일반적인 작업 흐름은 테스트 의존성을 추가하고, 빌드 파일에서 테스트 태스크를 구성하고, 테스트를 추가한 뒤 실행하는 거예요.
브라우저 테스트를 위해 다음 중에서 선택할 수 있어요.
- Karma 테스트 러너
- 브라우저 테스트용 새 DSL
Karma 프로젝트는 deprecated 처리됐어요. 새 기능이나 버그 수정은 기대되지 않아요. 대안으로 브라우저 테스트용 새 Kotlin DSL을 사용해 보세요.
브라우저 테스트용 새 DSL은 현재 Experimental 상태예요. 언제든 변경될 수 있어요. @OptIn(ExperimentalJsTestDsl::class) 어노테이션으로 옵트인해야 해요.
테스트 의존성 추가하기
멀티플랫폼 프로젝트를 만들 때 commonTest에서 의존성 하나만 사용해서 JavaScript 타깃을 포함한 모든 소스 세트에 테스트 의존성을 추가할 수 있어요.
// build.gradle.kts
kotlin {
sourceSets {
commonTest.dependencies {
implementation(kotlin("test")) // Enables test annotations and functionality in JS
}
}
}
// build.gradle
kotlin {
sourceSets {
commonTest {
dependencies {
implementation kotlin("test") // Enables test annotations and functionality in JS
}
}
}
}
브라우저 구성하기
Kotlin/JS에서 특정 브라우저를 대상으로 테스트를 실행할 수 있어요. 그러려면 Gradle 빌드 파일의 browser {} 구성 블록에서 설정을 조정해요.
기본적으로 플러그인은 Headless Chrome을 사용해서 브라우저 테스트를 실행해요. Kotlin Multiplatform Gradle 플러그인에는 기본적으로 어떤 브라우저도 번들로 포함되지 않아요. 추가 브라우저를 활성화하려면 Karma에서는 testTask {} 블록을, 브라우저 테스트용 새 DSL에서는 test {} 블록을 사용해요. 사용할 수 있는 모든 옵션은 여기에서 확인할 수 있어요.
kotlin {
js {
browser {
testTask {
useKarma {
useIe()
useSafari()
useFirefox()
useChrome()
useChromeCanary()
useChromeHeadless()
usePhantomJS()
useOpera()
}
}
}
}
}
Karma를 사용할 때는 타깃 시스템(로컬 또는 CI)에 필요한 모든 브라우저를 설치해야 해요.
Karma 기능에 대한 자세한 내용은 Set up a Kotlin/JS project를 참고하세요.
import org.jetbrains.kotlin.gradle.ExperimentalJsTestDsl
kotlin {
js {
browser {
@OptIn(ExperimentalJsTestDsl::class)
test {
chromium()
firefox()
webkit() // Safari browser
}
}
}
}
브라우저 테스트용 새 DSL에서는 Kotlin Multiplatform Gradle 플러그인이 playwright install 명령을 사용해서 첫 실행 시 필요한 브라우저를 설치해요. 그러면 Playwright가 이 브라우저들의 위치를 관리하며, 로컬에 설치된 브라우저는 사용하지 않아요.
브라우저 테스트용 새 DSL에서 사용할 수 있는 추가 설정은 Advanced configuration을 참고하세요.
테스트 추가하기
테스트가 제대로 실행되는지 확인하려면 다음 내용으로 src/jsTest/kotlin/AppTest.kt 파일을 만들어요.
import kotlin.test.Test
import kotlin.test.assertEquals
@Test
fun thingsShouldWork() {
assertEquals(listOf(3,2,1), listOf(1,2,3).reversed())
}
@Test
fun thingsShouldBreak() {
assertEquals(listOf(1,2,3), listOf(1,2,3).reversed())
}
테스트 실행하기
브라우저에서 테스트를 실행하려면 jsBrowserTest 태스크를 실행하거나, IntelliJ IDEA의 거터 아이콘을 사용해서 모든 테스트나 개별 테스트를 실행해요.
명령줄에서 테스트를 실행하고 싶다면 Gradle 래퍼를 사용해요.
./gradlew jsBrowserTest
IntelliJ IDEA에서 테스트를 실행한 뒤에는 Run 도구 창에 테스트 결과가 표시돼요. 실패한 테스트를 클릭하면 스택 트레이스를 볼 수 있고, 더블클릭하면 해당 테스트 구현으로 이동할 수 있어요.
어떤 방식으로 테스트를 실행했든 간에 각 테스트 실행 후에는 Gradle이 만든 형식화된 테스트 리포트를 build/reports/tests/jsBrowserTest/index.html에서 찾을 수 있어요. 이 파일을 브라우저에서 열면 테스트 결과의 또 다른 개요를 볼 수 있어요.
위 스니펫에 있는 예시 테스트 세트를 사용한다면, 하나는 통과하고 하나는 실패해서 성공률 50%가 돼요. 개별 테스트 케이스에 대한 자세한 정보를 얻으려면 제공된 링크를 사용해요.
고급 구성
이 섹션은 브라우저 테스트용 새 실험적 DSL에만 적용돼요.
브라우저 테스트용 새 DSL은 미니멀하고 도구에 구애받지 않도록 설계됐어요. 현재 구현에는 다음이 포함돼요.
- Playwright — Chromium, Firefox, WebKit(Safari) 브라우저 엔진을 지원하는 브라우저 드라이버 겸 배포 관리자 역할을 해요.
- Mocha — 테스트 러너 역할을 해요.
- webpack — 번들러 역할을 해요 (향후 릴리스에서 Vite로 교체될 예정이에요).
이 DSL은 타임아웃, 헤드리스 모드, 러너별 옵션을 Gradle 프로퍼티로 노출해서, 러너 사이에 기본값을 공유하고 특정 브라우저에 대해 override하며 providers로 값을 지연(lazily) 계산할 수 있어요.
import org.jetbrains.kotlin.gradle.ExperimentalJsTestDsl
import kotlin.time.Duration.Companion.seconds
kotlin {
js {
browser {
@OptIn(ExperimentalJsTestDsl::class)
test {
// Configures the default timeout for all runners with kotlin.Duration
timeout = 30.seconds
// Configures headless mode using Gradle providers
headless = providers
.environmentVariable("IS_IN_CI")
.map { it.toBoolean() }
.orElse(false)
// Enables and configures the Chromium runner with a custom name
chromium("chromium-no-webgl2") {
// Overrides the default timeout for this runner
timeout = 10.seconds
// Chromium-specific extra launch argument
launchArgs.add("--disable-webgl2")
}
// Enables the Firefox runner
firefox()
// Enables and configures the WebKit runner
webkit("safari") {
timeout = 35.seconds
}
}
}
}
}
모든 테스트 러너의 옵션을 test {} 블록에서 직접 설정할 수 있어요. 특정 러너에 대해 이 공통 옵션을 override하려면 그 러너에 사용자 지정 이름을 주고 러너 블록 안에서 다른 값을 제공해요. 이 예제에서 Chromium과 WebKit(Safari) 브라우저는 각각 10초와 35초의 타임아웃을 사용하고, Firefox는 공통 타임아웃인 30초를 사용해요.
각 러너는 자신만의 이름으로 등록되므로, 테스트 리포트에서 특정 결과가 어떤 브라우저에서 나왔는지 알 수 있어요.
플러그인 저자를 위한 구성
이 섹션은 브라우저 테스트용 새 실험적 DSL에만 적용돼요.
Kotlin Multiplatform Gradle 플러그인 위에 Gradle 플러그인을 작성한다면, 브라우저 테스트용 새 DSL을 통해 브라우저 러너와 생성된 테스트 번들의 위치에도 접근할 수 있어요.
Kotlin은 기본 test runner page를 사용해서 브라우저 테스트를 실행하기 위한 테스트 번들을 생성해요. testsLocation 프로퍼티에서 다른 위치를 가리켜서 이를 교체할 수 있어요.
kotlin {
js {
browser {
@OptIn(ExperimentalJsTestDsl::class)
test {
// Implement customJsTestsLocation to modify or replace the default JS test bundle
@OptIn(DelicateKotlinGradlePluginApi::class)
testsLocation = customJsTestsLocation(extendFrom = defaultTestsLocationProvider)
chromium()
}
}
}
}
사용자 지정 테스트 번들러에는 자신만의 개발 서버, 번들러, 테스트 러너를 포함할 수 있어요. defaultTestsLocationProvider 프로퍼티는 기본 위치에 접근할 수 있게 해 줘서, 모든 것을 처음부터 구현하는 대신 그 위에서 확장할 수 있어요.
각 테스트 위치는 KotlinJsTestsLocation 인터페이스를 통해 생성된 테스트 번들이 있는 디렉터리(bundleLocation), 테스트 페이지 이름(testHtmlFileName), 브라우저가 여는 URL(url)을 노출해요.
이 API들에 접근할 수 있으므로 다음을 할 수 있어요.
- 브라우저가 여는 URL을 커스터마이즈. 각 브라우저 러너는 자신만의 테스트 위치를 가지므로,
test {}블록에서 모든 러너에 대해, 또는 특정 러너에 대해 override할 수 있어요. - 번들 위치 자체를 override. 예를 들어 번들에 추가 파일을 포함시킬 수 있어요.
- 생성된 테스트 번들을 후처리. 브라우저가 파일을 열기 전에 자신만의 태스크를 등록하고 파일을 수정할 수 있어요. 예를 들어
test.html에 자신만의 구성을 주입할 수 있어요.
이 API들로 플러그인을 만들 때는 다음 제한 사항을 유의하세요.
subtarget.test를 구성하면 새 테스트 파이프라인이 활성화되고 Karma가 비활성화돼요. 현재 사용자가 어느 파이프라인을 선택했는지 안정적으로 감지할 방법이 없어요.- 특정 브라우저 러너를 지연(lazily) 구성할 안정적인 방법이 없으므로,
afterEvaluate에서 구성이 이뤄져야 해요. 사용자에게 테스트 위치를 명시적으로 설정하도록 요청하거나myPluginChromium()같은 데코레이팅 함수를 노출하는 것을 고려해 보세요.
피드백 남기기
브라우저 테스트용 새 DSL은 활발히 개발 중이에요. 디버깅 같은 새 기능이 다음 Kotlin 릴리스에 계획되어 있어요.
YouTrack이나 #javascript Slack 채널에 피드백을 남겨 주시면 감사하겠어요.