Tooling, testing, and IDE-based verification
Domain 4 covers the build, test, and IDE workflow used to verify Kotlin code. Questions focus on Gradle Kotlin DSL configuration, test framework setup, coroutine testing, and interpreting IDE feedback.
Build configuration
A JVM project typically uses build.gradle.kts with plugins { kotlin("jvm") version "..." }. Dependencies use configurations: implementation is available to compile and runtime but not exposed to consumers; testImplementation is only for test compilation and execution. For JUnit 5, configure tasks.test { useJUnitPlatform() }; without it the test task may find no tests. Keep the Kotlin plugin and standard library versions aligned.
Testing and verification
kotlin.test provides annotations and assertions that map to the configured framework. assertEquals(expected, actual) takes the expected value first. Backticked function names produce readable reports. assertFailsWith<T> checks exceptions. For suspending code, use runTest from kotlinx-coroutines-test; it uses virtual time, so delay is skipped rather than slept, and it fails a test that exceeds its timeout.
In the IDE, red markers are compiler errors, yellow markers are warnings or inspections. Use breakpoints and Evaluate Expression to inspect state, and run a single test or a coverage run to verify a branch.
Worked example
class CartTest {
@Test
fun `adding an item increases size`() = runTest {
val cart = Cart()
cart.add("A")
assertEquals(1, cart.size)
}
}
Reasoning: runTest supplies a test scope and virtual time. The backticked name documents behavior. A fresh Cart per test avoids shared state. assertEquals receives expected 1 before actual cart.size, so a failure message reads correctly.
Traps
Putting test libraries in implementation leaks them into production. Forgetting useJUnitPlatform() often produces a successful build with zero tests. Using Thread.sleep or runBlocking in a coroutine test makes it slow or flaky; use virtual time and test dispatchers.