CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-kotest--kotest-assertions-shared-jvm

Core assertion building blocks for Kotest testing framework providing foundational utilities like shouldBe for all platforms

Pending
Overview
Eval results
Files

collection-inspectors.mddocs/

Collection Inspectors

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.

Capabilities

Universal Collection Inspectors

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

/**
 * Assert that all elements in the collection satisfy the given predicate
 * @param fn Assertion function to apply to each element
 * @return The original collection for chaining
 */
inline fun <T, C : Collection<T>> C.forAll(fn: (T) -> Unit): C

/**
 * Assert that exactly one element satisfies the predicate
 * @param fn Assertion function to apply to each element
 * @return The original collection for chaining
 */
inline fun <T, C : Collection<T>> C.forOne(fn: (T) -> Unit): C

/**
 * Assert that exactly k elements satisfy the predicate
 * @param k The exact number of elements that should satisfy the predicate
 * @param fn Assertion function to apply to each element
 * @return The original collection for chaining
 */
inline fun <T, C : Collection<T>> C.forExactly(k: Int, fn: (T) -> Unit): C

/**
 * Assert that some elements (at least 1) satisfy the predicate
 * @param fn Assertion function to apply to each element
 * @return The original collection for chaining
 */
inline fun <T, C : Collection<T>> C.forSome(fn: (T) -> Unit): C

/**
 * Assert that any element satisfies the predicate (alias for forSome)
 * @param fn Assertion function to apply to each element
 * @return The original collection for chaining
 */
inline fun <T, C : Collection<T>> C.forAny(fn: (T) -> Unit): C

/**
 * Assert that at least one element satisfies the predicate
 * @param fn Assertion function to apply to each element
 * @return The original collection for chaining
 */
inline fun <T, C : Collection<T>> C.forAtLeastOne(fn: (T) -> Unit): C

/**
 * Assert that at least k elements satisfy the predicate
 * @param k The minimum number of elements that should satisfy the predicate
 * @param fn Assertion function to apply to each element
 * @return The original collection for chaining
 */
inline fun <T, C : Collection<T>> C.forAtLeast(k: Int, fn: (T) -> Unit): C

/**
 * Assert that at most one element satisfies the predicate
 * @param fn Assertion function to apply to each element
 * @return The original collection for chaining
 */
inline fun <T, C : Collection<T>> C.forAtMostOne(fn: (T) -> Unit): C

/**
 * Assert that at most k elements satisfy the predicate
 * @param k The maximum number of elements that should satisfy the predicate
 * @param fn Assertion function to apply to each element
 * @return The original collection for chaining
 */
inline fun <T, C : Collection<T>> C.forAtMost(k: Int, fn: (T) -> Unit): C

/**
 * Assert that no elements satisfy the predicate
 * @param fn Assertion function to apply to each element
 * @return The original collection for chaining
 */
inline fun <T, C : Collection<T>> C.forNone(fn: (T) -> Unit): C

/**
 * Assert that exactly one element exists and satisfies the predicate
 * @param fn Assertion function to apply to the single element
 * @return The single element in the collection
 */
fun <T, C : Collection<T>> C.forSingle(fn: (T) -> Unit): T

Map-Specific Inspectors

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

/**
 * Assert that all keys in the map satisfy the predicate
 * @param fn Assertion function to apply to each key
 * @return The original map for chaining
 */
inline fun <K, V, C : Map<K, V>> C.forAllKeys(fn: (K) -> Unit): C

/**
 * Assert that all values in the map satisfy the predicate
 * @param fn Assertion function to apply to each value
 * @return The original map for chaining
 */
inline fun <K, V, C : Map<K, V>> C.forAllValues(fn: (V) -> Unit): C

/**
 * Assert that all entries in the map satisfy the predicate
 * @param fn Assertion function to apply to each entry
 * @return The original map for chaining
 */
inline fun <K, V, C : Map<K, V>> C.forAll(fn: (Map.Entry<K, V>) -> Unit): C

/**
 * Assert that exactly one key satisfies the predicate
 * @param fn Assertion function to apply to each key
 * @return The original map for chaining
 */
inline fun <K, V, C : Map<K, V>> C.forOneKey(fn: (K) -> Unit): C

/**
 * Assert that exactly one value satisfies the predicate
 * @param fn Assertion function to apply to each value
 * @return The original map for chaining
 */
inline fun <K, V, C : Map<K, V>> C.forOneValue(fn: (V) -> Unit): C

/**
 * Assert that exactly one entry satisfies the predicate
 * @param fn Assertion function to apply to each entry
 * @return The original map for chaining
 */
inline fun <K, V, C : Map<K, V>> C.forOne(fn: (Map.Entry<K, V>) -> Unit): C

/**
 * Assert that exactly k keys satisfy the predicate
 * @param k The exact number of keys that should satisfy the predicate
 * @param fn Assertion function to apply to each key
 * @return The original map for chaining
 */
inline fun <K, V, C : Map<K, V>> C.forKeysExactly(k: Int, fn: (K) -> Unit): C

/**
 * Assert that exactly k values satisfy the predicate
 * @param k The exact number of values that should satisfy the predicate
 * @param fn Assertion function to apply to each value
 * @return The original map for chaining
 */
inline fun <K, V, C : Map<K, V>> C.forValuesExactly(k: Int, fn: (V) -> Unit): C

// Similar patterns exist for forSome, forAny, forAtLeast, forAtMost, forNone
// with Keys, Values, and Entry variants

Array Inspectors

All collection inspector functions are also available for arrays.

/**
 * Assert that all elements in the array satisfy the predicate
 * @param fn Assertion function to apply to each element
 * @return The original array for chaining
 */
inline fun <T> Array<T>.forAll(fn: (T) -> Unit): Array<T>

/**
 * Assert that exactly one element in the array satisfies the predicate
 * @param fn Assertion function to apply to each element
 * @return The original array for chaining
 */
inline fun <T> Array<T>.forOne(fn: (T) -> Unit): Array<T>

// All other quantifier functions (forExactly, forSome, forAny, etc.) 
// follow the same pattern for arrays

Sequence Inspectors

All collection inspector functions are available for sequences.

/**
 * Assert that all elements in the sequence satisfy the predicate
 * @param fn Assertion function to apply to each element
 * @return The original sequence for chaining
 */
inline fun <T> Sequence<T>.forAll(fn: (T) -> Unit): Sequence<T>

/**
 * Assert that exactly one element in the sequence satisfies the predicate
 * @param fn Assertion function to apply to each element
 * @return The original sequence for chaining
 */
inline fun <T> Sequence<T>.forOne(fn: (T) -> Unit): Sequence<T>

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

String/CharSequence Inspectors

Character-level inspection for strings and character sequences.

/**
 * Assert that all characters in the string satisfy the predicate
 * @param fn Assertion function to apply to each character
 * @return The original string for chaining
 */
inline fun CharSequence.forAll(fn: (Char) -> Unit): CharSequence

/**
 * Assert that exactly one character satisfies the predicate
 * @param fn Assertion function to apply to each character
 * @return The original string for chaining
 */
inline fun CharSequence.forOne(fn: (Char) -> Unit): CharSequence

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

Usage Examples

Basic Collection Testing

import io.kotest.inspectors.*
import io.kotest.matchers.*

// Test all elements match a condition
listOf(2, 4, 6, 8).forAll { 
    it % 2 shouldBe 0  // All numbers are even
}

// Test exactly one element matches
listOf(1, 2, 3, 4).forOne { 
    it > 3  // Only one number is greater than 3
}

// Test some elements match
listOf(1, 2, 3, 4, 5).forSome { 
    it > 3  // Some numbers are greater than 3 (4 and 5)
}

// Test none match
listOf(1, 3, 5, 7).forNone { 
    it % 2 shouldBe 0  // No numbers are even
}

Quantified Testing

import io.kotest.inspectors.*
import io.kotest.matchers.*

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

// Exactly 2 elements should be even
numbers.forExactly(2) { it % 2 shouldBe 0 }

// At least 3 elements should be less than 6
numbers.forAtLeast(3) { it should beLessThan(6) }

// At most 1 element should be greater than 4
numbers.forAtMost(1) { it should beGreaterThan(4) }

Map Testing

import io.kotest.inspectors.*
import io.kotest.matchers.*

val userAges = mapOf(
    "Alice" to 25,
    "Bob" to 30,
    "Charlie" to 35
)

// Test all keys are valid names
userAges.forAllKeys { name ->
    name.length should beGreaterThan(0)
    name.first().isUpperCase() shouldBe true
}

// Test all values are valid ages
userAges.forAllValues { age ->
    age should beInRange(0..120)
}

// Test all entries as pairs
userAges.forAll { (name, age) ->
    name.isNotEmpty() shouldBe true
    age should beGreaterThan(0)
}

String Testing

import io.kotest.inspectors.*
import io.kotest.matchers.*

// Test all characters in a string
"HELLO".forAll { char ->
    char.isUpperCase() shouldBe true
}

// Test exactly one character matches
"Hello World".forOne { char ->
    char shouldBe 'W'
}

// Test some characters are spaces
"Hello World Test".forSome { char ->
    char shouldBe ' '
}

// Test no characters are digits
"HelloWorld".forNone { char ->
    char.isDigit() shouldBe true
}

Array Testing

import io.kotest.inspectors.*
import io.kotest.matchers.*

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

// All temperatures should be reasonable
temperatures.forAll { temp ->
    temp should beInRange(0.0..50.0)
}

// Exactly one temperature should be above 23
temperatures.forOne { temp ->
    temp should beGreaterThan(23.0)
}

Complex Object Testing

import io.kotest.inspectors.*
import io.kotest.matchers.*

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

val users = listOf(
    User("Alice", 25, "alice@example.com"),
    User("Bob", 30, "bob@example.com"),
    User("Charlie", 35, "charlie@example.com")
)

// All users should have valid data
users.forAll { user ->
    user.name.isNotEmpty() shouldBe true
    user.age should beInRange(0..120)
    user.email should contain("@")
}

// Exactly one user should be named "Bob"
users.forOne { user ->
    user.name shouldBe "Bob"
}

// Some users should be over 30
users.forSome { user ->
    user.age should beGreaterThan(30)
}

Chaining Inspectors

import io.kotest.inspectors.*
import io.kotest.matchers.*

// Chain multiple inspector calls
val data = listOf(1, 2, 3, 4, 5)

data
    .forAll { it should beGreaterThan(0) }  // All positive
    .forSome { it % 2 shouldBe 0 }          // Some even
    .forAtMost(2) { it should beGreaterThan(3) }  // At most 2 > 3

Single Element Testing

import io.kotest.inspectors.*
import io.kotest.matchers.*

// When you expect exactly one element and want to return it
val singleUser = listOf(User("Alice", 25, "alice@example.com"))

val user = singleUser.forSingle { user ->
    user.name shouldBe "Alice"
    user.age shouldBe 25
}

// user is now of type User, not List<User>
user.email shouldBe "alice@example.com"

Error Reporting

The inspector functions provide detailed error messages when assertions fail:

// If this fails, you get a detailed report showing which elements failed
listOf(1, 2, 3, 4).forAll { it should beLessThan(3) }
// Error: 2 elements failed the predicate:
// [2]: expected to be < 3 but was 3
// [3]: expected to be < 3 but was 4

Performance Considerations

  • Inline Functions: All inspector functions are inline for zero runtime overhead
  • Short-Circuiting: Functions like forOne and forNone stop as soon as the condition is met
  • Memory Efficiency: Sequences are processed lazily without intermediate collections
  • Type Safety: Full compile-time type checking with no runtime type erasure issues

Install with Tessl CLI

npx tessl i tessl/maven-io-kotest--kotest-assertions-shared-jvm

docs

collection-inspectors.md

core-matchers.md

data-driven-testing.md

error-handling.md

index.md

tile.json