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")
}