正确做法是使用 ./gradlew jvmTest 仅运行 JVM 平台测试,因 test 是聚合任务会触发所有平台测试而易失败;各平台测试任务名严格为 {target}Test,--tests 等参数仅对具体平台任务生效,exclude 等配置也需逐平台设置。

只运行 JVM 平台测试:别用 test,用 jvmTest
在 Kotlin Multiplatform 项目中,test 是一个聚合任务(aggregating task),它默认会触发所有已启用平台的测试任务——包括 jvmTest、iosX64Test、jsBrowserTest 等。直接执行 ./gradlew test 必然失败或超时,尤其当 iOS 或 JS 测试环境未就绪时。
正确做法是跳过聚合任务,直奔目标平台任务:
-
./gradlew jvmTest:仅运行 JVM 平台的测试(对应commonTest+jvmTest) -
./gradlew iosSimulatorArm64Test:仅运行 iOS 模拟器(Apple Silicon)上的测试 -
./gradlew jsBrowserTest:仅运行 JS 浏览器环境测试(需 Chromium 安装)
这些任务名由 Kotlin Gradle 插件自动生成,命名规则为 {target}Test(如 androidUnitTest、iosArm64Test)。不支持通配符缩写,比如 iosTest 不存在,必须写全平台标识。
排除某个平台测试:禁用其 Test 任务,而非修改 test
如果你希望在 CI 中固定只跑 JVM 和 JS,但彻底跳过 iOS 测试(比如 macOS 机器不可用),不能靠 test { enabled = false } —— 这个配置对 test 本身生效,不影响子项目里独立的 iosX64Test 任务。
真正起效的方式是显式禁用对应平台的测试任务:
- 在根
build.gradle.kts或对应子模块中添加:tasks.named("iosX64Test") { enabled = false } - 也可批量禁用:
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinTest>().configureEach { if (name.contains("ios", ignoreCase = true)) enabled = false } - 注意:禁用后该任务仍会出现在
./gradlew tasks列表中,但执行时跳过,不会报错
运行单个测试类或方法:平台任务才支持 --tests
--tests 参数只对具体平台的 Test 任务有效,对聚合的 test 无效。例如:
- ✅ 正确:
./gradlew jvmTest --tests "*Network*"或./gradlew jvmTest --tests "com.example.MyTest.testSuccess" - ❌ 无效:
./gradlew test --tests "com.example.MyTest"(会被忽略,且可能报 warning) - JS 平台需额外注意:
jsBrowserTest默认使用 Karma + Chrome,若本地无 Chrome,可切到 Node.js 模式:js { browser { testTask { useKarma { useChromeHeadless() } } } }
常见陷阱:为什么 exclude 在 test 里不生效
很多人试图在根项目的 test 配置块里写 exclude "**/IntegrationTest.class",结果毫无作用。这是因为:
-
test本身不加载任何测试类,它只是触发各平台子任务的“调度器” -
exclude是Test类型任务的属性,只对jvmTest、iosX64Test等生效 - 想全局过滤,必须逐个配置平台任务:
tasks.withType<org.gradle.api.tasks.testing.Test>().configureEach { exclude("**/SlowTest.class") exclude("**/Legacy*.class") } - 路径模式匹配的是编译后的类名(如
com/example/MyTest.class),不是源码路径
跨平台测试最易被忽略的一点:每个平台的测试类路径、依赖范围、甚至断言库行为都可能不同。哪怕同一个 expect 函数,在 commonTest 里调用 assertTrue,JVM 走 JUnit,JS 走 Mocha,iOS 走 XCTest——它们的错误堆栈格式、超时机制、异步等待逻辑全不一样。别假设“跑过了 jvmTest 就等于其他平台也稳”。


















