Kotlin Multiplatform 只有 commonTest,为何仍运行各平台测试?
是的,这是正常行为。在 Kotlin Multiplatform 的默认配置下,即使所有测试代码都放在 commonTest 中,也需要通过具体平台的测试任务运行。因此,执行 ./gradlew build 时出现 jvmTest、iosSimulatorArm64Test 和 jsBrowserTest,并不表示 Gradle 错误地查找了不存在的平台测试。
不过,任务名称本身不能说明构建失败的原因。问题中没有提供完整错误日志,仅凭没有平台专属测试文件也无法直接解释失败原因。
为什么只有 commonTest,还会运行平台测试?
commonTest 是共享测试源码集,不是独立的运行平台。默认情况下,其中的测试会参与各个已声明目标的测试编译,再由相应平台的测试运行器执行。jvmTest 等平台测试源码集用于补充只适用于该平台的测试。这种关系由 Kotlin Multiplatform 的默认项目结构建立,通常不需要创建对应目录就会生效。Kotlin 官方项目结构说明
例如,在默认源码集关系下:
jvmTest运行编译到 JVM 的共享测试,以及存在的 JVM 专属测试。iosSimulatorArm64Test在相应 iOS 模拟器环境中运行共享测试,以及存在的平台专属测试。jsBrowserTest在配置的浏览器测试环境中运行共享测试,以及存在的 JS 专属测试。
测试只需编写一份,就可以在多个运行环境中分别验证。相同的共享代码可能调用不同的平台实现,因此多平台执行有实际意义。Kotlin 官方测试教程
问题中执行的是 ./gradlew build。在标准 Gradle 生命周期中,build 依赖 assemble 和 check,测试通常接入验证流程,因此构建会触发测试。具体有哪些任务进入执行图,还取决于项目声明的目标、插件配置和宿主机支持情况。Gradle Base Plugin 文档
如何排查“没有测试可运行”的失败?
先定位第一个失败任务并查看具体错误,不要根据目录是否存在判断原因。以下命令假设模块路径为 :library;如果 settings.gradle.kts 中配置了其他名称,需要替换任务路径。
./gradlew :library:tasks --all
./gradlew :library:build --dry-run
./gradlew :library:jvmTest --info --stacktrace
--dry-run 用于查看将要执行的任务,不会实际运行测试。如果失败发生在其他平台,将最后一个命令中的任务替换为 iosSimulatorArm64Test 或 jsBrowserTest。
随后按错误类型检查:
- 测试没有被发现:检查文件是否位于
library/src/commonTest/kotlin或显式配置的源码目录中,测试函数是否带有正确的@Test,以及测试依赖、运行器和筛选条件是否匹配。 - 测试环境启动失败:根据日志检查浏览器测试环境、iOS 模拟器或相关工具链,先处理环境错误。
- 测试断言失败:测试已经被发现并执行,需要查看具体用例的失败信息。
对于 JVM 的 Gradle Test 任务,还要区分“没有测试源码”和“有测试源码却没有发现测试”。Gradle 的 failOnNoDiscoveredTests 控制后者是否导致失败,不能直接套用于所有 Kotlin/JS 或 Kotlin/Native 测试任务。未确认失败类型之前,不宜通过关闭失败检查来掩盖问题。Gradle Test API 文档
怎样验证 commonTest 的配置?
先检查模块的 build.gradle.kts 中是否为 commonTest 声明了 kotlin.test。下面的配置应合并到现有配置中,无需重复添加已有依赖:
kotlin {
sourceSets {
commonTest.dependencies {
implementation(kotlin("test"))
}
}
}
然后在 library/src/commonTest/kotlin/SharedTest.kt 中放入一个最小测试,验证测试发现与执行链路:
import kotlin.test.Test
import kotlin.test.assertEquals
class SharedTest {
@Test
fun addsNumbers() {
assertEquals(4, 2 + 2)
}
}
共享测试应使用 kotlin.test.Test 等跨平台 API。各平台仍需具备与其配置匹配的测试运行器。例如,JVM 如果显式使用 JUnit Platform,就需要匹配的测试框架依赖与引擎,不能只凭 @Test 注解判断配置完整。Kotlin 官方测试教程
如果开发时只想运行一个平台怎么办?
直接执行对应平台的任务即可。例如,只在 JVM 上运行共享测试:
./gradlew :library:jvmTest
该任务仍会运行参与 JVM 测试编译的 commonTest 测试,无须把测试复制到 jvmTest 目录。其他平台的测试可以在具备相应运行环境时分别执行。
要确定这次构建失败的具体原因,还需要失败任务的完整日志,以及项目使用的 Kotlin、Gradle 版本和相关测试配置。
备注:内容仅供参考。
