Testing And Benchmarking in Kotlin

Unit testing is an important part of writing principled Kotlin programs. The org.junit.jupiter package provides the tools we need to write unit tests, and the gradle test command runs tests.

For the sake of demonstration, this code is in the default package, but it could be any package. Testing code typically lives in the same package as the code it tests.

import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource

// We'll be testing this simple implementation of an
// integer minimum. Typically, the code we're testing
// would be in a source file named something like
// `IntUtils.kt`, and the test file for it would then
// be named `IntUtilsTest.kt`.
fun intMin(a: Int, b: Int): Int = if (a < b) a else b

// A test is created by writing a function with the @Test annotation.
class IntMinTest {
    @Test
    fun testIntMinBasic() {
        val ans = intMin(2, -2)
        // assertEquals will report test failures but continue
        // executing the test. assertThrows or fail() will report test
        // failures and stop the test immediately.
        assertEquals(-2, ans, "IntMin(2, -2) should be -2")
    }

    // Writing tests can be repetitive, so it's idiomatic to
    // use a parameterized test style, where test inputs and
    // expected outputs are listed in a table and a single test
    // walks over them and performs the test logic.
    @ParameterizedTest
    @CsvSource(
        "0, 1, 0",
        "1, 0, 0",
        "2, -2, -2",
        "0, -1, -1",
        "-1, 0, -1"
    )
    fun testIntMinTableDriven(a: Int, b: Int, expected: Int) {
        val ans = intMin(a, b)
        assertEquals(expected, ans, "IntMin($a, $b) should be $expected")
    }
}

// Benchmark tests in Kotlin are typically done using a separate
// benchmarking library like JMH (Java Microbenchmark Harness).
// Here's a simple example of how you might set up a benchmark:

import org.openjdk.jmh.annotations.*
import java.util.concurrent.TimeUnit

@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
open class IntMinBenchmark {
    @Benchmark
    fun benchmarkIntMin() {
        intMin(1, 2)
    }
}

To run all tests in the current project in verbose mode, you would typically use a build tool like Gradle:

$ ./gradlew test --info

To run benchmarks, you would need to set up JMH in your project and run it through Gradle or directly. The exact command would depend on your project setup.

Remember that Kotlin integrates well with Java, so you can often use Java testing and benchmarking tools directly in your Kotlin projects.