or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

arguments.mdconfiguration-sources.mdcore-commands.mdexceptions.mdindex.mdoptions.mdparameter-groups.mdparameter-types.mdshell-completion.mdtesting-utilities.md

testing-utilities.mddocs/

0

# Testing Utilities

1

2

Test command execution with controlled input/output, environment variables, and terminal settings for comprehensive CLI testing.

3

4

## Capabilities

5

6

### CliktCommandTestResult

7

8

Data class containing the results of a test execution, including all output streams and exit status.

9

10

```kotlin { .api }

11

/**

12

* Result of testing a CliktCommand

13

* @param stdout Content written to standard output

14

* @param stderr Content written to standard error

15

* @param output Combined stdout and stderr content

16

* @param statusCode Exit status code (0 for success, non-zero for errors)

17

*/

18

data class CliktCommandTestResult(

19

val stdout: String,

20

val stderr: String,

21

val output: String, // stdout + stderr combined

22

val statusCode: Int

23

)

24

```

25

26

**Usage Examples:**

27

28

```kotlin

29

class HelloCommand : CliktCommand() {

30

private val name by argument()

31

override fun run() = echo("Hello $name!")

32

}

33

34

val result = HelloCommand().test("World")

35

assertEquals("Hello World!\n", result.stdout)

36

assertEquals("", result.stderr)

37

assertEquals(0, result.statusCode)

38

```

39

40

### Test Function

41

42

Execute a command in a controlled test environment with configurable input, environment, and terminal settings.

43

44

```kotlin { .api }

45

/**

46

* Test a CliktCommand with controlled environment

47

* @param argv Command line arguments as a single string

48

* @param stdin Standard input content

49

* @param envvars Environment variables to set

50

* @param includeSystemEnvvars Include system environment variables

51

* @param ansiLevel ANSI color support level

52

* @param width Terminal width in characters

53

* @param height Terminal height in lines

54

* @return CliktCommandTestResult containing all output and status

55

*/

56

fun CliktCommand.test(

57

argv: String,

58

stdin: String = "",

59

envvars: Map<String, String> = emptyMap(),

60

includeSystemEnvvars: Boolean = false,

61

ansiLevel: AnsiLevel = AnsiLevel.NONE,

62

width: Int = 79,

63

height: Int = 24

64

): CliktCommandTestResult

65

66

fun CliktCommand.test(

67

vararg argv: String,

68

stdin: String = "",

69

envvars: Map<String, String> = emptyMap(),

70

includeSystemEnvvars: Boolean = false,

71

ansiLevel: AnsiLevel = AnsiLevel.NONE,

72

width: Int = 79,

73

height: Int = 24

74

): CliktCommandTestResult

75

76

fun CliktCommand.test(

77

argv: List<String>,

78

stdin: String = "",

79

envvars: Map<String, String> = emptyMap(),

80

includeSystemEnvvars: Boolean = false,

81

ansiLevel: AnsiLevel = AnsiLevel.NONE,

82

width: Int = 79,

83

height: Int = 24

84

): CliktCommandTestResult

85

86

fun CliktCommand.test(

87

argv: Array<String>,

88

stdin: String = "",

89

envvars: Map<String, String> = emptyMap(),

90

includeSystemEnvvars: Boolean = false,

91

ansiLevel: AnsiLevel = AnsiLevel.NONE,

92

width: Int = 79,

93

height: Int = 24

94

): CliktCommandTestResult

95

```

96

97

**Usage Examples:**

98

99

```kotlin

100

class ConfigCommand : CliktCommand() {

101

private val config by option("--config", envvar = "CONFIG_FILE")

102

override fun run() = echo("Config: $config")

103

}

104

105

// Test with arguments

106

val result1 = ConfigCommand().test("--config myconfig.yml")

107

assertEquals("Config: myconfig.yml\n", result1.stdout)

108

109

// Test with environment variables

110

val result2 = ConfigCommand().test("", envvars = mapOf("CONFIG_FILE" to "env.yml"))

111

assertEquals("Config: env.yml\n", result2.stdout)

112

113

// Test with stdin

114

class ReadCommand : CliktCommand() {

115

override fun run() {

116

val input = readLine()

117

echo("Read: $input")

118

}

119

}

120

121

val result3 = ReadCommand().test("", stdin = "test input\n")

122

assertEquals("Read: test input\n", result3.stdout)

123

```

124

125

## Testing Patterns

126

127

### Basic Command Testing

128

129

Test simple commands with arguments and options:

130

131

```kotlin

132

class GreetCommand : CliktCommand() {

133

private val greeting by option("-g", "--greeting").default("Hello")

134

private val name by argument()

135

136

override fun run() = echo("$greeting $name!")

137

}

138

139

@Test

140

fun testGreeting() {

141

val result = GreetCommand().test("World")

142

assertEquals("Hello World!\n", result.stdout)

143

assertEquals(0, result.statusCode)

144

}

145

146

@Test

147

fun testCustomGreeting() {

148

val result = GreetCommand().test("--greeting Hi Alice")

149

assertEquals("Hi Alice!\n", result.stdout)

150

}

151

```

152

153

### Error Testing

154

155

Test error conditions and validate error messages:

156

157

```kotlin

158

class RequiredOptionCommand : CliktCommand() {

159

private val required by option("--required").required()

160

override fun run() = echo("Value: $required")

161

}

162

163

@Test

164

fun testMissingRequired() {

165

val result = RequiredOptionCommand().test("")

166

assertTrue(result.statusCode != 0)

167

assertTrue(result.stderr.contains("Missing option"))

168

}

169

```

170

171

### Environment Variable Testing

172

173

Test environment variable integration:

174

175

```kotlin

176

class EnvCommand : CliktCommand() {

177

private val value by option("--value", envvar = "TEST_VALUE")

178

override fun run() = echo("Value: $value")

179

}

180

181

@Test

182

fun testEnvironmentVariable() {

183

val result = EnvCommand().test("", envvars = mapOf("TEST_VALUE" to "from-env"))

184

assertEquals("Value: from-env\n", result.stdout)

185

}

186

```

187

188

### Subcommand Testing

189

190

Test commands with subcommands:

191

192

```kotlin

193

class MainCommand : CliktCommand() {

194

override fun run() = Unit

195

}

196

197

class SubCommand : CliktCommand(name = "sub") {

198

private val option by option("--opt")

199

override fun run() = echo("Sub: $option")

200

}

201

202

@Test

203

fun testSubcommand() {

204

val main = MainCommand()

205

main.subcommands(SubCommand())

206

207

val result = main.test("sub --opt value")

208

assertEquals("Sub: value\n", result.stdout)

209

}

210

```

211

212

### Terminal Width Testing

213

214

Test help output formatting with different terminal widths:

215

216

```kotlin

217

class HelpCommand : CliktCommand(help = "A command with a very long help description that will wrap at different terminal widths")

218

219

@Test

220

fun testNarrowTerminal() {

221

val result = HelpCommand().test("--help", width = 40)

222

assertTrue(result.stdout.contains("A command with a very"))

223

}

224

225

@Test

226

fun testWideTerminal() {

227

val result = HelpCommand().test("--help", width = 120)

228

assertTrue(result.stdout.contains("A command with a very long help description"))

229

}

230

```

231

232

### Interactive Input Testing

233

234

Test commands that read from stdin:

235

236

```kotlin

237

class InteractiveCommand : CliktCommand() {

238

override fun run() {

239

echo("Enter name:")

240

val name = readLine()

241

echo("Hello $name!")

242

}

243

}

244

245

@Test

246

fun testInteractive() {

247

val result = InteractiveCommand().test("", stdin = "Alice\n")

248

assertTrue(result.stdout.contains("Enter name:"))

249

assertTrue(result.stdout.contains("Hello Alice!"))

250

}

251

```

252

253

## Advanced Testing Features

254

255

### ANSI Color Testing

256

257

Test colored output with different ANSI support levels:

258

259

```kotlin

260

import com.github.ajalt.mordant.rendering.AnsiLevel

261

262

@Test

263

fun testColorOutput() {

264

val colorResult = command.test("", ansiLevel = AnsiLevel.TRUECOLOR)

265

val noColorResult = command.test("", ansiLevel = AnsiLevel.NONE)

266

267

// Colored output will contain ANSI escape sequences

268

assertTrue(colorResult.stdout.contains("\u001B["))

269

270

// No-color output will not contain escape sequences

271

assertFalse(noColorResult.stdout.contains("\u001B["))

272

}

273

```

274

275

### System Environment Testing

276

277

Control whether system environment variables are included:

278

279

```kotlin

280

@Test

281

fun testSystemEnvExclusion() {

282

// Test with only specified environment variables

283

val result = command.test("",

284

envvars = mapOf("TEST_VAR" to "test"),

285

includeSystemEnvvars = false

286

)

287

288

// System PATH variable should not be available

289

assertFalse(result.stdout.contains(System.getenv("PATH") ?: ""))

290

}

291

```

292

293

## Best Practices

294

295

### Test Organization

296

297

```kotlin

298

class CommandTest {

299

private lateinit var command: MyCommand

300

301

@BeforeEach

302

fun setup() {

303

command = MyCommand()

304

}

305

306

@Test

307

fun testSuccessCase() {

308

val result = command.test("valid arguments")

309

assertEquals(0, result.statusCode)

310

assertTrue(result.stderr.isEmpty())

311

}

312

313

@Test

314

fun testErrorCase() {

315

val result = command.test("invalid arguments")

316

assertNotEquals(0, result.statusCode)

317

assertTrue(result.stderr.isNotEmpty())

318

}

319

}

320

```

321

322

### Assertion Helpers

323

324

```kotlin

325

fun assertSuccess(result: CliktCommandTestResult) {

326

assertEquals(0, result.statusCode, "Command should succeed")

327

assertTrue(result.stderr.isEmpty(), "No error output expected")

328

}

329

330

fun assertError(result: CliktCommandTestResult, expectedMessage: String) {

331

assertNotEquals(0, result.statusCode, "Command should fail")

332

assertTrue(result.stderr.contains(expectedMessage),

333

"Expected error message not found: $expectedMessage")

334

}

335

```

336

337

The testing utilities provide comprehensive support for testing CLI applications with full control over the execution environment, making it easy to verify command behavior, error handling, and output formatting across different scenarios.