or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

collection-inspectors.mdcore-matchers.mddata-driven-testing.mderror-handling.mdindex.md

collection-inspectors.mddocs/

0

# Collection Inspectors

1

2

Collection inspectors provide a powerful DSL for testing properties across collection elements using quantifier functions. They support collections, arrays, sequences, maps, and strings with comprehensive assertion capabilities for different testing scenarios.

3

4

## Capabilities

5

6

### Universal Collection Inspectors

7

8

These functions work with any `Collection<T>` and return the original collection for chaining.

9

10

```kotlin { .api }

11

/**

12

* Assert that all elements in the collection satisfy the given predicate

13

* @param fn Assertion function to apply to each element

14

* @return The original collection for chaining

15

*/

16

inline fun <T, C : Collection<T>> C.forAll(fn: (T) -> Unit): C

17

18

/**

19

* Assert that exactly one element satisfies the predicate

20

* @param fn Assertion function to apply to each element

21

* @return The original collection for chaining

22

*/

23

inline fun <T, C : Collection<T>> C.forOne(fn: (T) -> Unit): C

24

25

/**

26

* Assert that exactly k elements satisfy the predicate

27

* @param k The exact number of elements that should satisfy the predicate

28

* @param fn Assertion function to apply to each element

29

* @return The original collection for chaining

30

*/

31

inline fun <T, C : Collection<T>> C.forExactly(k: Int, fn: (T) -> Unit): C

32

33

/**

34

* Assert that some elements (at least 1) satisfy the predicate

35

* @param fn Assertion function to apply to each element

36

* @return The original collection for chaining

37

*/

38

inline fun <T, C : Collection<T>> C.forSome(fn: (T) -> Unit): C

39

40

/**

41

* Assert that any element satisfies the predicate (alias for forSome)

42

* @param fn Assertion function to apply to each element

43

* @return The original collection for chaining

44

*/

45

inline fun <T, C : Collection<T>> C.forAny(fn: (T) -> Unit): C

46

47

/**

48

* Assert that at least one element satisfies the predicate

49

* @param fn Assertion function to apply to each element

50

* @return The original collection for chaining

51

*/

52

inline fun <T, C : Collection<T>> C.forAtLeastOne(fn: (T) -> Unit): C

53

54

/**

55

* Assert that at least k elements satisfy the predicate

56

* @param k The minimum number of elements that should satisfy the predicate

57

* @param fn Assertion function to apply to each element

58

* @return The original collection for chaining

59

*/

60

inline fun <T, C : Collection<T>> C.forAtLeast(k: Int, fn: (T) -> Unit): C

61

62

/**

63

* Assert that at most one element satisfies the predicate

64

* @param fn Assertion function to apply to each element

65

* @return The original collection for chaining

66

*/

67

inline fun <T, C : Collection<T>> C.forAtMostOne(fn: (T) -> Unit): C

68

69

/**

70

* Assert that at most k elements satisfy the predicate

71

* @param k The maximum number of elements that should satisfy the predicate

72

* @param fn Assertion function to apply to each element

73

* @return The original collection for chaining

74

*/

75

inline fun <T, C : Collection<T>> C.forAtMost(k: Int, fn: (T) -> Unit): C

76

77

/**

78

* Assert that no elements satisfy the predicate

79

* @param fn Assertion function to apply to each element

80

* @return The original collection for chaining

81

*/

82

inline fun <T, C : Collection<T>> C.forNone(fn: (T) -> Unit): C

83

84

/**

85

* Assert that exactly one element exists and satisfies the predicate

86

* @param fn Assertion function to apply to the single element

87

* @return The single element in the collection

88

*/

89

fun <T, C : Collection<T>> C.forSingle(fn: (T) -> Unit): T

90

```

91

92

### Map-Specific Inspectors

93

94

Specialized inspectors for testing maps with separate key, value, and entry predicates.

95

96

```kotlin { .api }

97

/**

98

* Assert that all keys in the map satisfy the predicate

99

* @param fn Assertion function to apply to each key

100

* @return The original map for chaining

101

*/

102

inline fun <K, V, C : Map<K, V>> C.forAllKeys(fn: (K) -> Unit): C

103

104

/**

105

* Assert that all values in the map satisfy the predicate

106

* @param fn Assertion function to apply to each value

107

* @return The original map for chaining

108

*/

109

inline fun <K, V, C : Map<K, V>> C.forAllValues(fn: (V) -> Unit): C

110

111

/**

112

* Assert that all entries in the map satisfy the predicate

113

* @param fn Assertion function to apply to each entry

114

* @return The original map for chaining

115

*/

116

inline fun <K, V, C : Map<K, V>> C.forAll(fn: (Map.Entry<K, V>) -> Unit): C

117

118

/**

119

* Assert that exactly one key satisfies the predicate

120

* @param fn Assertion function to apply to each key

121

* @return The original map for chaining

122

*/

123

inline fun <K, V, C : Map<K, V>> C.forOneKey(fn: (K) -> Unit): C

124

125

/**

126

* Assert that exactly one value satisfies the predicate

127

* @param fn Assertion function to apply to each value

128

* @return The original map for chaining

129

*/

130

inline fun <K, V, C : Map<K, V>> C.forOneValue(fn: (V) -> Unit): C

131

132

/**

133

* Assert that exactly one entry satisfies the predicate

134

* @param fn Assertion function to apply to each entry

135

* @return The original map for chaining

136

*/

137

inline fun <K, V, C : Map<K, V>> C.forOne(fn: (Map.Entry<K, V>) -> Unit): C

138

139

/**

140

* Assert that exactly k keys satisfy the predicate

141

* @param k The exact number of keys that should satisfy the predicate

142

* @param fn Assertion function to apply to each key

143

* @return The original map for chaining

144

*/

145

inline fun <K, V, C : Map<K, V>> C.forKeysExactly(k: Int, fn: (K) -> Unit): C

146

147

/**

148

* Assert that exactly k values satisfy the predicate

149

* @param k The exact number of values that should satisfy the predicate

150

* @param fn Assertion function to apply to each value

151

* @return The original map for chaining

152

*/

153

inline fun <K, V, C : Map<K, V>> C.forValuesExactly(k: Int, fn: (V) -> Unit): C

154

155

// Similar patterns exist for forSome, forAny, forAtLeast, forAtMost, forNone

156

// with Keys, Values, and Entry variants

157

```

158

159

### Array Inspectors

160

161

All collection inspector functions are also available for arrays.

162

163

```kotlin { .api }

164

/**

165

* Assert that all elements in the array satisfy the predicate

166

* @param fn Assertion function to apply to each element

167

* @return The original array for chaining

168

*/

169

inline fun <T> Array<T>.forAll(fn: (T) -> Unit): Array<T>

170

171

/**

172

* Assert that exactly one element in the array satisfies the predicate

173

* @param fn Assertion function to apply to each element

174

* @return The original array for chaining

175

*/

176

inline fun <T> Array<T>.forOne(fn: (T) -> Unit): Array<T>

177

178

// All other quantifier functions (forExactly, forSome, forAny, etc.)

179

// follow the same pattern for arrays

180

```

181

182

### Sequence Inspectors

183

184

All collection inspector functions are available for sequences.

185

186

```kotlin { .api }

187

/**

188

* Assert that all elements in the sequence satisfy the predicate

189

* @param fn Assertion function to apply to each element

190

* @return The original sequence for chaining

191

*/

192

inline fun <T> Sequence<T>.forAll(fn: (T) -> Unit): Sequence<T>

193

194

/**

195

* Assert that exactly one element in the sequence satisfies the predicate

196

* @param fn Assertion function to apply to each element

197

* @return The original sequence for chaining

198

*/

199

inline fun <T> Sequence<T>.forOne(fn: (T) -> Unit): Sequence<T>

200

201

// All other quantifier functions follow the same pattern for sequences

202

```

203

204

### String/CharSequence Inspectors

205

206

Character-level inspection for strings and character sequences.

207

208

```kotlin { .api }

209

/**

210

* Assert that all characters in the string satisfy the predicate

211

* @param fn Assertion function to apply to each character

212

* @return The original string for chaining

213

*/

214

inline fun CharSequence.forAll(fn: (Char) -> Unit): CharSequence

215

216

/**

217

* Assert that exactly one character satisfies the predicate

218

* @param fn Assertion function to apply to each character

219

* @return The original string for chaining

220

*/

221

inline fun CharSequence.forOne(fn: (Char) -> Unit): CharSequence

222

223

// All other quantifier functions follow the same pattern for CharSequence

224

```

225

226

## Usage Examples

227

228

### Basic Collection Testing

229

230

```kotlin

231

import io.kotest.inspectors.*

232

import io.kotest.matchers.*

233

234

// Test all elements match a condition

235

listOf(2, 4, 6, 8).forAll {

236

it % 2 shouldBe 0 // All numbers are even

237

}

238

239

// Test exactly one element matches

240

listOf(1, 2, 3, 4).forOne {

241

it > 3 // Only one number is greater than 3

242

}

243

244

// Test some elements match

245

listOf(1, 2, 3, 4, 5).forSome {

246

it > 3 // Some numbers are greater than 3 (4 and 5)

247

}

248

249

// Test none match

250

listOf(1, 3, 5, 7).forNone {

251

it % 2 shouldBe 0 // No numbers are even

252

}

253

```

254

255

### Quantified Testing

256

257

```kotlin

258

import io.kotest.inspectors.*

259

import io.kotest.matchers.*

260

261

val numbers = listOf(1, 2, 3, 4, 5)

262

263

// Exactly 2 elements should be even

264

numbers.forExactly(2) { it % 2 shouldBe 0 }

265

266

// At least 3 elements should be less than 6

267

numbers.forAtLeast(3) { it should beLessThan(6) }

268

269

// At most 1 element should be greater than 4

270

numbers.forAtMost(1) { it should beGreaterThan(4) }

271

```

272

273

### Map Testing

274

275

```kotlin

276

import io.kotest.inspectors.*

277

import io.kotest.matchers.*

278

279

val userAges = mapOf(

280

"Alice" to 25,

281

"Bob" to 30,

282

"Charlie" to 35

283

)

284

285

// Test all keys are valid names

286

userAges.forAllKeys { name ->

287

name.length should beGreaterThan(0)

288

name.first().isUpperCase() shouldBe true

289

}

290

291

// Test all values are valid ages

292

userAges.forAllValues { age ->

293

age should beInRange(0..120)

294

}

295

296

// Test all entries as pairs

297

userAges.forAll { (name, age) ->

298

name.isNotEmpty() shouldBe true

299

age should beGreaterThan(0)

300

}

301

```

302

303

### String Testing

304

305

```kotlin

306

import io.kotest.inspectors.*

307

import io.kotest.matchers.*

308

309

// Test all characters in a string

310

"HELLO".forAll { char ->

311

char.isUpperCase() shouldBe true

312

}

313

314

// Test exactly one character matches

315

"Hello World".forOne { char ->

316

char shouldBe 'W'

317

}

318

319

// Test some characters are spaces

320

"Hello World Test".forSome { char ->

321

char shouldBe ' '

322

}

323

324

// Test no characters are digits

325

"HelloWorld".forNone { char ->

326

char.isDigit() shouldBe true

327

}

328

```

329

330

### Array Testing

331

332

```kotlin

333

import io.kotest.inspectors.*

334

import io.kotest.matchers.*

335

336

val temperatures = arrayOf(20.5, 22.0, 19.8, 23.2, 21.1)

337

338

// All temperatures should be reasonable

339

temperatures.forAll { temp ->

340

temp should beInRange(0.0..50.0)

341

}

342

343

// Exactly one temperature should be above 23

344

temperatures.forOne { temp ->

345

temp should beGreaterThan(23.0)

346

}

347

```

348

349

### Complex Object Testing

350

351

```kotlin

352

import io.kotest.inspectors.*

353

import io.kotest.matchers.*

354

355

data class User(val name: String, val age: Int, val email: String)

356

357

val users = listOf(

358

User("Alice", 25, "alice@example.com"),

359

User("Bob", 30, "bob@example.com"),

360

User("Charlie", 35, "charlie@example.com")

361

)

362

363

// All users should have valid data

364

users.forAll { user ->

365

user.name.isNotEmpty() shouldBe true

366

user.age should beInRange(0..120)

367

user.email should contain("@")

368

}

369

370

// Exactly one user should be named "Bob"

371

users.forOne { user ->

372

user.name shouldBe "Bob"

373

}

374

375

// Some users should be over 30

376

users.forSome { user ->

377

user.age should beGreaterThan(30)

378

}

379

```

380

381

### Chaining Inspectors

382

383

```kotlin

384

import io.kotest.inspectors.*

385

import io.kotest.matchers.*

386

387

// Chain multiple inspector calls

388

val data = listOf(1, 2, 3, 4, 5)

389

390

data

391

.forAll { it should beGreaterThan(0) } // All positive

392

.forSome { it % 2 shouldBe 0 } // Some even

393

.forAtMost(2) { it should beGreaterThan(3) } // At most 2 > 3

394

```

395

396

### Single Element Testing

397

398

```kotlin

399

import io.kotest.inspectors.*

400

import io.kotest.matchers.*

401

402

// When you expect exactly one element and want to return it

403

val singleUser = listOf(User("Alice", 25, "alice@example.com"))

404

405

val user = singleUser.forSingle { user ->

406

user.name shouldBe "Alice"

407

user.age shouldBe 25

408

}

409

410

// user is now of type User, not List<User>

411

user.email shouldBe "alice@example.com"

412

```

413

414

## Error Reporting

415

416

The inspector functions provide detailed error messages when assertions fail:

417

418

```kotlin

419

// If this fails, you get a detailed report showing which elements failed

420

listOf(1, 2, 3, 4).forAll { it should beLessThan(3) }

421

// Error: 2 elements failed the predicate:

422

// [2]: expected to be < 3 but was 3

423

// [3]: expected to be < 3 but was 4

424

```

425

426

## Performance Considerations

427

428

- **Inline Functions**: All inspector functions are `inline` for zero runtime overhead

429

- **Short-Circuiting**: Functions like `forOne` and `forNone` stop as soon as the condition is met

430

- **Memory Efficiency**: Sequences are processed lazily without intermediate collections

431

- **Type Safety**: Full compile-time type checking with no runtime type erasure issues