CtrlK
BlogDocsLog inGet started
Tessl Logo

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

Common test assertions and utilities for Kotlin multiplatform projects

Pending
Overview
Eval results
Files

framework-integration.mddocs/

Framework Integration

Core interfaces and utilities for integrating with different testing frameworks across Kotlin multiplatform targets. This system provides a pluggable architecture that allows the same test code to work with JUnit, TestNG, JavaScript testing frameworks, and native testing environments.

Capabilities

Asserter Interface

The core interface that abstracts assertion logic and provides integration points for different testing frameworks.

/**
 * Interface that abstracts the assertion logic and can be implemented by 
 * any testing framework to provide consistent assertion behavior across platforms.
 */
interface Asserter {
    /**
     * Marks a test as failed with the specified message.
     * @param message The failure message, or null for default message
     * @return Nothing (this function never returns normally)
     */
    fun fail(message: String?): Nothing
    
    /**
     * Marks a test as failed with the specified message and cause.
     * @param message The failure message, or null for default message  
     * @param cause The underlying cause of the failure, or null if none
     * @return Nothing (this function never returns normally)
     */
    fun fail(message: String?, cause: Throwable?): Nothing
    
    /**
     * Asserts that the value is true.
     * @param lazyMessage Lazy-evaluated message provider for failure cases
     * @param actual The boolean value to test
     */
    fun assertTrue(lazyMessage: () -> String?, actual: Boolean)
    
    /**
     * Asserts that the value is true.
     * @param message The failure message, or null for default
     * @param actual The boolean value to test
     */
    fun assertTrue(message: String?, actual: Boolean)
    
    /**
     * Asserts that the expected and actual values are equal.
     * @param message The failure message, or null for default
     * @param expected The expected value
     * @param actual The actual value to compare
     */
    fun assertEquals(message: String?, expected: Any?, actual: Any?)
    
    /**
     * Asserts that the illegal and actual values are not equal.
     * @param message The failure message, or null for default
     * @param illegal The value that should not match
     * @param actual The actual value to compare
     */
    fun assertNotEquals(message: String?, illegal: Any?, actual: Any?)
    
    /**
     * Asserts that the expected and actual references are the same instance.
     * @param message The failure message, or null for default
     * @param expected The expected object reference
     * @param actual The actual object reference
     */
    fun assertSame(message: String?, expected: Any?, actual: Any?)
    
    /**
     * Asserts that the illegal and actual references are not the same instance.
     * @param message The failure message, or null for default
     * @param illegal The reference that should not match
     * @param actual The actual object reference
     */
    fun assertNotSame(message: String?, illegal: Any?, actual: Any?)
    
    /**
     * Asserts that the actual value is null.
     * @param message The failure message, or null for default
     * @param actual The value to test for null
     */
    fun assertNull(message: String?, actual: Any?)
    
    /**
     * Asserts that the actual value is not null.
     * @param message The failure message, or null for default
     * @param actual The value to test for non-null
     */
    fun assertNotNull(message: String?, actual: Any?)
}

AsserterContributor Interface

Interface for providing custom Asserter implementations in a pluggable way.

/**
 * Interface for providing Asserter instances. Implementations can be registered
 * to contribute custom assertion behavior for specific testing frameworks.
 */
interface AsserterContributor {
    /**
     * Provides an Asserter instance for the current testing context.
     * @return An Asserter implementation, or null if this contributor 
     *         cannot provide one for the current context
     */
    fun contribute(): Asserter?
}

Global Asserter Property

The global asserter property that holds the current assertion implementation.

/**
 * The current Asserter instance used by all assertion functions.
 * This can be replaced to integrate with different testing frameworks.
 * Defaults to DefaultAsserter if no framework-specific asserter is available.
 */
var asserter: Asserter

Usage Examples:

import kotlin.test.*

@Test
fun testCustomAsserterIntegration() {
    // Save the original asserter
    val originalAsserter = asserter
    
    try {
        // Install a custom asserter for specialized behavior
        asserter = CustomTestAsserter()
        
        // All assertions now use the custom asserter
        assertEquals("expected", "actual") // Uses CustomTestAsserter.assertEquals()
        assertTrue(false) // Uses CustomTestAsserter.assertTrue()
        
    } finally {
        // Restore original asserter
        asserter = originalAsserter
    }
}

class CustomTestAsserter : Asserter {
    override fun fail(message: String?): Nothing {
        throw CustomAssertionError(message ?: "Assertion failed")
    }
    
    override fun fail(message: String?, cause: Throwable?): Nothing {
        throw CustomAssertionError(message ?: "Assertion failed", cause)
    }
    
    override fun assertTrue(message: String?, actual: Boolean) {
        if (!actual) {
            fail(message ?: "Expected true but was false")
        }
    }
    
    override fun assertEquals(message: String?, expected: Any?, actual: Any?) {
        if (expected != actual) {
            fail(message ?: "Expected <$expected> but was <$actual>")
        }
    }
    
    // ... implement other methods
}

DefaultAsserter Object

The default asserter implementation used when no framework-specific asserter is available.

/**
 * Default Asserter implementation that provides basic assertion functionality
 * without depending on any specific testing framework.
 */
object DefaultAsserter : Asserter {
    /**
     * Throws AssertionError with the specified message.
     */
    override fun fail(message: String?): Nothing
    
    /**
     * Throws AssertionErrorWithCause with the specified message and cause.
     */
    override fun fail(message: String?, cause: Throwable?): Nothing
}

Platform-Specific Integration Examples

JVM Integration (JUnit)

// Custom JUnit asserter implementation
class JUnitAsserter : Asserter {
    override fun fail(message: String?): Nothing {
        org.junit.Assert.fail(message)
        throw AssertionError() // Never reached
    }
    
    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 implementations delegate to JUnit
}

// Register the asserter
class JUnitAsserterContributor : AsserterContributor {
    override fun contribute(): Asserter? {
        return if (isJUnitAvailable()) JUnitAsserter() else null
    }
    
    private fun isJUnitAvailable(): Boolean {
        return try {
            Class.forName("org.junit.Assert")
            true
        } catch (e: ClassNotFoundException) {
            false
        }
    }
}

JavaScript Integration

// Custom JavaScript asserter for Node.js environments
class NodeJSAsserter : Asserter {
    override fun fail(message: String?): Nothing {
        js("throw new Error(message || 'Assertion failed')")
    }
    
    override fun assertTrue(message: String?, actual: Boolean) {
        if (!actual) {
            fail(message ?: "Expected true but was false")
        }
    }
    
    override fun assertEquals(message: String?, expected: Any?, actual: Any?) {
        js("""
            const assert = require('assert');
            assert.deepStrictEqual(actual, expected, message);
        """)
    }
    
    // ... other implementations
}

Native Integration

// Custom native asserter implementation
class NativeAsserter : Asserter {
    override fun fail(message: String?): Nothing {
        // Native-specific error reporting
        platform.posix.fprintf(platform.posix.stderr, "ASSERTION FAILED: %s\n", message ?: "")
        platform.posix.exit(1)
        throw AssertionError() // Never reached
    }
    
    // ... other implementations using native APIs
}

Custom Framework Integration

Creating a Custom Testing Framework Integration

import kotlin.test.*

// Step 1: Implement the Asserter interface
class MyFrameworkAsserter : Asserter {
    override fun fail(message: String?): Nothing {
        MyTestFramework.reportFailure(message ?: "Test failed")
        throw MyFrameworkException(message)
    }
    
    override fun fail(message: String?, cause: Throwable?): Nothing {
        MyTestFramework.reportFailure(message ?: "Test failed", cause)
        throw MyFrameworkException(message, cause)
    }
    
    override fun assertTrue(message: String?, actual: Boolean) {
        if (!actual) {
            MyTestFramework.reportBooleanFailure(message, expected = true, actual = false)
            fail(message ?: "Expected true but was false")
        }
    }
    
    override fun assertEquals(message: String?, expected: Any?, actual: Any?) {
        if (expected != actual) {
            MyTestFramework.reportEqualityFailure(message, expected, actual)
            fail(message ?: "Expected <$expected> but was <$actual>")
        }
    }
    
    // Implement remaining methods...
}

// Step 2: Create an AsserterContributor
class MyFrameworkAsserterContributor : AsserterContributor {
    override fun contribute(): Asserter? {
        return if (MyTestFramework.isActive()) {
            MyFrameworkAsserter()
        } else {
            null
        }
    }
}

// Step 3: Register the contributor (usually done during framework initialization)
fun initializeMyFramework() {
    val contributor = MyFrameworkAsserterContributor()
    val customAsserter = contributor.contribute()
    if (customAsserter != null) {
        asserter = customAsserter
    }
}

Advanced Integration Features

// Enhanced asserter with additional framework-specific features
class EnhancedFrameworkAsserter : Asserter {
    private val testContext = MyFramework.getCurrentTestContext()
    
    override fun fail(message: String?): Nothing {
        // Capture additional context
        val stackTrace = Thread.currentThread().stackTrace
        val testMethod = stackTrace.find { it.methodName.startsWith("test") }
        
        MyFramework.reportDetailedFailure(
            message = message,
            testClass = testContext.testClass,
            testMethod = testMethod?.methodName,
            stackTrace = stackTrace
        )
        
        throw MyFrameworkException(message)
    }
    
    // Override other methods with enhanced reporting...
    
    override fun assertEquals(message: String?, expected: Any?, actual: Any?) {
        if (expected != actual) {
            // Enhanced diff reporting
            val diff = MyFramework.computeDiff(expected, actual)
            MyFramework.reportEqualityFailure(
                message = message,
                expected = expected,
                actual = actual,
                diff = diff
            )
            fail(buildEqualityMessage(message, expected, actual, diff))
        }
    }
    
    private fun buildEqualityMessage(
        userMessage: String?,
        expected: Any?,
        actual: Any?,
        diff: String
    ): String {
        val base = userMessage ?: "Assertion failed"
        return "$base\nExpected: $expected\nActual: $actual\nDiff:\n$diff"
    }
}

Error Handling and Framework Compatibility

The framework integration system handles various error scenarios gracefully:

  • Missing Framework: Falls back to DefaultAsserter if no framework-specific asserter is available
  • Framework Conflicts: Multiple asserter contributors can coexist; the first successful one is used
  • Runtime Switching: The asserter can be changed during test execution for specialized testing scenarios
@Test
fun testFrameworkFallback() {
    // This test works regardless of which testing framework is present
    assertEquals("expected", computeValue())
    assertTrue(isValid())
    
    // The underlying asserter handles framework-specific reporting
}

Install with Tessl CLI

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

docs

boolean-assertions.md

collection-assertions.md

equality-assertions.md

exception-testing.md

framework-integration.md

index.md

test-annotations.md

test-utilities.md

type-null-assertions.md

tile.json