CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-kotlin--kotlin-test

Multiplatform testing framework providing unified API for writing tests across all Kotlin platforms with assertions and test annotations.

Pending
Overview
Eval results
Files

asserter.mddocs/

Asserter Interface

The core assertion interface that can be customized for different testing frameworks and platforms. The Asserter interface provides the foundation for all assertion operations in Kotlin Test.

Capabilities

Asserter Interface

The main interface for implementing custom assertion backends.

/**
 * Abstracts the logic for performing assertions. Specific implementations can use
 * JUnit, TestNG, or other assertion facilities.
 */
interface Asserter {
    /**
     * Fails the current test with the specified message
     * @param message - The message to report
     * @return Nothing (function never returns)
     */
    fun fail(message: String?): Nothing
    
    /**
     * Fails the current test with the specified message and cause exception
     * @param message - The message to report  
     * @param cause - The exception to set as the root cause of the reported failure
     * @return Nothing (function never returns)
     */
    fun fail(message: String?, cause: Throwable?): Nothing
    
    /**
     * Asserts that the specified value is true
     * @param lazyMessage - Function to return a message to report if the assertion fails
     * @param actual - Boolean value to check
     */
    fun assertTrue(lazyMessage: () -> String?, actual: Boolean): Unit
    
    /**
     * Asserts that the specified value is true  
     * @param message - The message to report if the assertion fails
     * @param actual - Boolean value to check
     */
    fun assertTrue(message: String?, actual: Boolean): Unit
    
    /**
     * Asserts that the specified values are equal
     * @param message - The message to report if the assertion fails
     * @param expected - Expected value
     * @param actual - Actual value
     */
    fun assertEquals(message: String?, expected: Any?, actual: Any?): Unit
    
    /**
     * Asserts that the specified values are not equal
     * @param message - The message to report if the assertion fails
     * @param illegal - Value that should not match
     * @param actual - Actual value
     */  
    fun assertNotEquals(message: String?, illegal: Any?, actual: Any?): Unit
    
    /**
     * Asserts that the specified values are the same instance
     * @param message - The message to report if the assertion fails
     * @param expected - Expected object reference
     * @param actual - Actual object reference
     */
    fun assertSame(message: String?, expected: Any?, actual: Any?): Unit
    
    /**
     * Asserts that the specified values are not the same instance
     * @param message - The message to report if the assertion fails
     * @param illegal - Object reference that should not match
     * @param actual - Actual object reference
     */
    fun assertNotSame(message: String?, illegal: Any?, actual: Any?): Unit
    
    /**
     * Asserts that the specified value is null
     * @param message - The message to report if the assertion fails
     * @param actual - Value to check for nullness
     */
    fun assertNull(message: String?, actual: Any?): Unit
    
    /**
     * Asserts that the specified value is not null
     * @param message - The message to report if the assertion fails
     * @param actual - Value to check for non-nullness
     */
    fun assertNotNull(message: String?, actual: Any?): Unit
}

AsserterContributor Interface

Interface for providing Asserter instances based on context.

/**
 * Checks applicability and provides Asserter instance
 */
interface AsserterContributor {
    /**
     * Provides Asserter instance or null depending on the current context
     * @return Asserter instance or null if not applicable
     */
    fun contribute(): Asserter?
}

DefaultAsserter Object

Default implementation of the Asserter interface.

/**
 * Default Asserter implementation to avoid dependency on JUnit or TestNG
 */
object DefaultAsserter : Asserter

Current Asserter Property

Global property to access the current asserter instance.

/**
 * Current adapter providing assertion implementations
 * Gets the current asserter or looks up an available one
 */
val asserter: Asserter

Usage Examples

Using the Global Asserter

import kotlin.test.*

@Test
fun testUsingGlobalAsserter() {
    // The global asserter is used automatically by assertion functions
    val result = performCalculation()
    
    // These functions delegate to the current asserter
    assertTrue(result > 0)
    assertEquals(42, result)
    assertNotNull(result)
    
    // You can also use the asserter directly (though not typically needed)
    asserter.assertTrue("Result should be positive", result > 0)
    asserter.assertEquals("Should equal 42", 42, result)
}

Creating Custom Asserter

class CustomAsserter(private val testName: String) : Asserter {
    override fun fail(message: String?): Nothing {
        val fullMessage = "[$testName] ${message ?: "Test failed"}"
        throw AssertionError(fullMessage)
    }
    
    override fun fail(message: String?, cause: Throwable?): Nothing {
        val fullMessage = "[$testName] ${message ?: "Test failed"}"
        throw AssertionError(fullMessage, cause)
    }
    
    override fun assertTrue(message: String?, actual: Boolean) {
        if (!actual) {
            fail(message ?: "Expected value to be true")
        }
    }
    
    override fun assertEquals(message: String?, expected: Any?, actual: Any?) {
        if (expected != actual) {
            fail("${message ?: "Values should be equal"}: expected <$expected>, actual <$actual>")
        }
    }
    
    override fun assertNotEquals(message: String?, illegal: Any?, actual: Any?) {
        if (illegal == actual) {
            fail("${message ?: "Values should not be equal"}: illegal value <$actual>")
        }
    }
    
    override fun assertSame(message: String?, expected: Any?, actual: Any?) {
        if (expected !== actual) {
            fail("${message ?: "References should be same"}: expected <$expected>, actual <$actual>")
        }
    }
    
    override fun assertNotSame(message: String?, illegal: Any?, actual: Any?) {
        if (illegal === actual) {
            fail("${message ?: "References should not be same"}: illegal reference <$actual>")
        }
    }
    
    override fun assertNull(message: String?, actual: Any?) {
        if (actual != null) {
            fail("${message ?: "Value should be null"}: actual <$actual>")
        }
    }
    
    override fun assertNotNull(message: String?, actual: Any?) {
        if (actual == null) {
            fail(message ?: "Value should not be null")
        }
    }
}

Creating Custom AsserterContributor

class LoggingAsserterContributor : AsserterContributor {
    override fun contribute(): Asserter? {
        // Only provide the logging asserter in debug mode
        return if (isDebugMode()) {
            LoggingAsserter()
        } else {
            null
        }
    }
}

class LoggingAsserter : Asserter {
    private fun log(operation: String, message: String?) {
        println("[ASSERT] $operation: ${message ?: "no message"}")
    }
    
    override fun fail(message: String?): Nothing {
        log("FAIL", message)
        throw AssertionError(message)
    }
    
    override fun fail(message: String?, cause: Throwable?): Nothing {
        log("FAIL", "$message (caused by: ${cause?.message})")
        throw AssertionError(message, cause)
    }
    
    override fun assertTrue(message: String?, actual: Boolean) {
        log("ASSERT_TRUE", message)
        if (!actual) {
            throw AssertionError(message ?: "Expected true")
        }
    }
    
    override fun assertEquals(message: String?, expected: Any?, actual: Any?) {
        log("ASSERT_EQUALS", "$message: expected=$expected, actual=$actual")
        if (expected != actual) {
            throw AssertionError("Expected <$expected>, actual <$actual>")
        }
    }
    
    // ... implement other methods with logging
}

Platform-Specific Asserter Implementations

JUnit Asserter Integration

// This is how kotlin-test integrates with JUnit internally
class JUnitAsserter : Asserter {
    override fun fail(message: String?): Nothing {
        org.junit.Assert.fail(message)
        throw AssertionError() // Never reached, but needed for Nothing return type
    }
    
    override fun assertTrue(message: String?, actual: Boolean) {
        org.junit.Assert.assertTrue(message, actual)
    }
    
    override fun assertEquals(message: String?, expected: Any?, actual: Any?) {
        org.junit.Assert.assertEquals(message, expected, actual)
    }
    
    // ... other methods delegate to JUnit assertions
}

TestNG Asserter Integration

class TestNGAsserter : Asserter {
    override fun fail(message: String?): Nothing {
        org.testng.Assert.fail(message)
        throw AssertionError() // Never reached
    }
    
    override fun assertTrue(message: String?, actual: Boolean) {
        org.testng.Assert.assertTrue(actual, message)
    }
    
    override fun assertEquals(message: String?, expected: Any?, actual: Any?) {
        org.testng.Assert.assertEquals(actual, expected, message)
    }
    
    // ... other methods delegate to TestNG assertions
}

Custom Test Framework Integration

class MyFrameworkAsserter : Asserter {
    override fun fail(message: String?): Nothing {
        MyTestFramework.reportFailure(message ?: "Test failed")
        throw MyTestFramework.TestFailedException(message)
    }
    
    override fun assertTrue(message: String?, actual: Boolean) {
        if (!actual) {
            MyTestFramework.reportAssertion("assertTrue", message, false)
            fail(message ?: "Expected true")
        } else {
            MyTestFramework.reportAssertion("assertTrue", message, true)
        }
    }
    
    // ... implement other methods to integrate with your framework
}

Advanced Usage Patterns

Temporary Asserter Override

@Test
fun testWithCustomAsserter() {
    val originalAsserter = asserter
    val customAsserter = CustomAsserter("MyTest")
    
    try {
        // Temporarily override the asserter
        overrideAsserter(customAsserter)
        
        // All assertions now use the custom asserter
        assertTrue(true) // Will use CustomAsserter
        assertEquals(42, 42) // Will use CustomAsserter
        
    } finally {
        // Restore original asserter
        overrideAsserter(originalAsserter)
    }
}

// Helper function to override asserter (internal API)
fun overrideAsserter(newAsserter: Asserter): Asserter {
    // This uses internal kotlin-test API
    return kotlin.test.overrideAsserter(newAsserter) ?: DefaultAsserter
}

Asserter Chain

class ChainedAsserter(private val asserters: List<Asserter>) : Asserter {
    override fun fail(message: String?): Nothing {
        // Fail using the first asserter in the chain
        asserters.firstOrNull()?.fail(message) ?: throw AssertionError(message)
    }
    
    override fun assertTrue(message: String?, actual: Boolean) {
        // Execute assertion on all asserters in chain
        for (asserter in asserters) {
            asserter.assertTrue(message, actual)
        }
    }
    
    // ... implement other methods to delegate to all asserters
}

@Test
fun testWithChainedAsserters() {
    val loggingAsserter = LoggingAsserter()
    val junitAsserter = JUnitAsserter()
    val chainedAsserter = ChainedAsserter(listOf(loggingAsserter, junitAsserter))
    
    overrideAsserter(chainedAsserter)
    
    // This will both log the assertion AND use JUnit's assertion
    assertTrue(5 > 3)
}

Platform-Specific Utilities

currentStackTrace Function (JVM Only)

⚠️ JVM Platform Only - This function is only available when running tests on the JVM platform.

Returns the current stack trace as an array of stack trace elements for debugging and diagnostic purposes.

/**
 * Returns an array of stack trace elements, each representing one stack frame
 * The first element represents the top of the stack (where currentStackTrace was called)
 * @return Array of StackTraceElement representing the call stack
 */
inline fun currentStackTrace(): Array<StackTraceElement>

Usage Examples:

import kotlin.test.*

@Test
fun testStackTraceCapture() {
    // Capture stack trace at current location
    val stackTrace = currentStackTrace()
    
    // Examine the top frame (where currentStackTrace was called)
    val topFrame = stackTrace[0]
    println("Called from: ${topFrame.fileName}:${topFrame.lineNumber}")
    println("Method: ${topFrame.methodName}")
    println("Class: ${topFrame.className}")
    
    // Verify we captured the right location
    assertEquals("AssertionTests.kt", topFrame.fileName)
    assertTrue(topFrame.lineNumber > 0)
}

// Custom diagnostic assertion using stack trace
fun assertWithLocation(condition: Boolean, message: String) {
    if (!condition) {
        val location = currentStackTrace()[0]
        fail("$message at ${location.fileName}:${location.lineNumber}")
    }
}

@Test
fun testCustomDiagnosticAssertion() {
    val value = 42
    
    // This will provide detailed location info if it fails
    assertWithLocation(value == 42, "Value should be 42")
    
    // Example of failure (commented out)
    // assertWithLocation(value == 99, "This will show exact location")
}

// Advanced: Custom test framework integration
class DetailedAsserter : Asserter {
    override fun fail(message: String?): Nothing {
        val location = currentStackTrace()[1] // Skip this frame
        throw AssertionError("$message\n  at ${location.className}.${location.methodName}(${location.fileName}:${location.lineNumber})")
    }
    
    override fun assertTrue(message: String?, actual: Boolean) {
        if (!actual) {
            fail(message ?: "Assertion failed")
        }
    }
    
    // ... implement other Asserter methods
}

@Test
fun testDetailedStackTraceDiagnostics() {
    // This custom asserter will provide detailed location info
    val detailedAsserter = DetailedAsserter()
    
    try {
        detailedAsserter.assertTrue("This should pass", true)
        detailedAsserter.assertTrue("This will fail with location", false)
    } catch (e: AssertionError) {
        // The error message will include precise location information
        assertContains(e.message ?: "", "AssertionTests.kt")
    }
}

Platform Notes:

  • Availability: Only available on JVM platform
  • Performance: Minimal overhead as it uses Java's built-in stack trace mechanism
  • Use Cases: Debugging, custom error reporting, diagnostic utilities
  • Stack Frame Structure: First element [0] is the location where currentStackTrace() was called
  • Integration: Used internally by the todo() function for location reporting

This function is particularly useful for building custom assertion utilities, debugging test failures, and creating diagnostic tools that need to report precise location information.

Install with Tessl CLI

npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-test

docs

annotations.md

asserter.md

basic-assertions.md

collection-assertions.md

exception-testing.md

index.md

type-null-assertions.md

tile.json