🏆 Featured in Android Weekly and Kotlin Weekly!

Updated (Jan 21, 2026): View Changelog

Today, I’ll show you how to configure Kotest for iOS, Linux, JVM and Android on a KMP project.

We’ll focus on the Gradle configuration. You can find the full template in this repository: Kotest-KMP-Setup

The base config (Native targets)

First, we need the Kotest and KSP gradle plugin.

plugins {
    id("org.jetbrains.kotlin.multiplatform")
    id("com.android.kotlin.multiplatform.library")
    id("io.kotest")
    id("com.google.devtools.ksp")
}

And then, add the kotest engine as a dependency in commonTest.

kotlin {
    iosX64()
    iosArm64()
    iosSimulatorArm64()
    linuxX64()

    sourceSets {
        commonTest {
            dependencies {
                implementation("io.kotest:kotest-framework-engine:<kotest-version>")
            }
        }
    }
}

This setup is enough for iOS and Linux targets. You can already add kotest specs on commonTest or one of the native test source sets and execute them with ./gradlew allTests, or execute them for a single target, like: ./gradlew iosSimulatorArm64Test.

JVM

JVM test run on the JUnit Platform. First we enable the jvm target.

kotlin {
    jvm()
}

Then, we configure tests to run on the JUnit Platform

kotlin {
    jvm {
        testRuns.all {
            executionTask {
                useJUnitPlatform() 
            }
        }
    }
}

And we add the following dependency to jvmTest.

kotlin {
    sourceSets {
        jvmTest {
            dependencies {
                implementation("io.kotest:kotest-runner-junit6:<kotest-version>")
            }
        }
    }
}

Kotest tests will run with the standard jvmTest.

Android

Android test also run on the JUnit Platform.

The new plugin (com.android.kotlin.multiplatform.library) doesn’t yet provide a clean DSL to configure unit tests like the deprecated (com.android.library) plugin did.

In the old plugin, we could do this:

// This does NOT work with the new KMP Android library plugin
android.testOptions {
   unitTests.all { it.useJUnitPlatform() }
}

Because that API is missing, we have to configure the task directly by its name. Interestingly, tasks.named("testAndroidHostTest") often fails to resolve during the configuration phase in this specific setup, so using tasks.withType<Test> { } with a name check is the most reliable workaround.

kotlin {
    androidLibrary {
        // other android configs
        withHostTest { } // enable unit tests (now called host tests)
    }
}

tasks.withType<Test>().configureEach {
    if (name == "testAndroidHostTest") {
        useJUnitPlatform()
    }
}

And adding the same lib we added for JVM on the androidHostTest source set.

kotlin {
    sourceSets {
        getByName("androidHostTest") {
            dependencies {
                implementation("io.kotest:kotest-runner-junit5:<kotest-version>")
            }
        }
    }
}

Running the tests

Once configured, you have two main ways to run your suite:

  • ./gradlew allTests: Runs all multiplatform tests (including the manually wired jvmKotest).
  • ./gradlew check: The standard Gradle lifecycle task that runs all tests and verification tasks (lint, etc.).

Changelog

January 21, 2026: Kotest 6.1.0 & JUnit 6

Updated the guide to reflect breaking changes in Kotest 6.1.0.

  • Change: Kotest has dropped the support for the kotest engine on JVM. The JVM target now runs exclusively on the JUnit Platform.
  • Change: Support for Junit 6
  • Action: Removed the section on setting up JVM test with the kotest engine
  • Action: Replaced kotest-runner-junit5 with kotest-runner-junit6

Need the old setup? If you are stuck on Kotest 6.0.x or older, you can view the previous version of this guide’s code in the repository history: 📂 View Code for Kotest 6.0.7 (GitHub Commit)