Skip to content

Testing Clikt Commands

Clikt includes the test extension to help testing commands and their output.

@Test
fun testHello() {
    val command = Hello()
    val result = command.test("--name Foo")
    assertEqual(result.stdout, "Hello, Foo!")
    assertEqual(result.exitCode, 0)
    assertEqual(command.name, "Foo")
}
class Hello: CliktCommand() {
    val name by option()
    override fun run() {
        echo("Hello, $name!")
    }
}

Calling test will run the command with the given arguments and return a result object that contains the captured outputs and result status code. You can check the captured output with the stdout property of the result, errors output with stderr, or both combined in with output.

Caution

Output printed with Kotlin’s print and println functions are not captured. Use echo instead.

Testing Environment Variables

You can set environment variables for your command by passing in a map of envvars.

@Test
fun testHello() {
    val command = Hello()
    val result = command.test("", envvars=mapOf("HELLO_NAME" to "Foo"))
    assertEqual(result.stdout, "Hello, Foo!")
}
class Hello: CliktCommand() {
    val name by option(envvar="HELLO_NAME")
    override fun run() {
        echo("Hello, $name!")
    }
}

To keep tests reproducible, only the envvar values you provide to test are visible to the command. To include system envvars as well, pass includeSystemEnvvars=true to test.

Testing Prompt Options

If you use prompt options, you can use the stdin parameter of test to pass a string containing all the lines of input. If you have multiple prompts, each input should be separated by \n.

@Test
fun testAdder() {
    val command = Adder()
    val result = command.test("", stdin = "2\n3")
    assertEqual(result.stdout, "first: second: result: 2 + 3 = 5")
}
class Adder : TestCommand() {
    val first by option().prompt()
    val second by option().prompt()

    override fun run_() {
        echo("result: $first + $second = ${first + second}")
    }
}

Custom Testing

If the test helper doesn’t cover all the use cases you need to test, you can run your command yourself.

If your command uses environment variables, you can configure the context to return test values for them.

To capture output, override the command’s console.

By default CliktCommand.main, calls exitProcess when errors occur, which would stop tests from running. You have a couple of choices to handle this:

Configuring exitProcess

CliktCommand.main calls Context.exitProcess to exit the process. You can set that to an empty lambda to skip it, or one that captures the status value if you want to check it in you tests.

Using parse instead of main

Instead of calling main, you can use CliktCommand.parse, which throws exceptions with error details rather than printing the details and exiting the process. See the documentation on exceptions for more information on the exceptions that can be thrown.