Kotlin unit tests with lambdas and runCatching

A unit test calls a function with chosen input and compares the result with the expected one. Kotlin projects usually use JUnit or kotlin.test, but the idea fits in a few lines. A test helper takes a name and a lambda, runs the lambda, and prints PASS or FAIL. Kotlin's check and require functions throw IllegalStateException and IllegalArgumentException when a condition is false, which makes them natural assertions.

Kotlin
fun percent(text: String): Int {
    val value = text.toIntOrNull() ?: throw NumberFormatException("not a number: $text")
    require(value in 0..100) { "out of range: $value" }
    return value
}

var failures = 0

fun test(name: String, body: () -> Unit) {
    val outcome = runCatching(body)
    if (outcome.isSuccess) {
        println("PASS $name")
    } else {
        failures++
        println("FAIL $name: ${outcome.exceptionOrNull()?.message}")
    }
}

inline fun <reified E : Throwable> assertThrows(code: () -> Unit) {
    val error = runCatching(code).exceptionOrNull()
    check(error is E) { "expected ${E::class.simpleName} but got ${error?.let { it::class.simpleName }}" }
}

fun main() {
    test("parses 42") { check(percent("42") == 42) }
    test("accepts the boundary 100") { check(percent("100") == 100) }
    test("rejects 101") { assertThrows<IllegalArgumentException> { percent("101") } }
    test("rejects text") { assertThrows<NumberFormatException> { percent("abc") } }
    test("a wrong expectation") { check(percent("7") == 8) }
    println("failures: $failures")
}
Read the full lesson