/kotlin-test
Enforce TDD workflow for Kotlin. Write Kotest tests first, then implement. Verify 80%+ coverage with Kover.
> /plugin marketplace add affaan-m/everything-claude-code > /plugin install ecc@ecc
How it fires
How this command gets triggered: by you, by Claude, or both.
- Fires itselfClaude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/kotlin-test
Context preview
What this command does when you run it.
Enforce TDD workflow for Kotlin. Write Kotest tests first, then implement. Verify 80%+ coverage with Kover.
Command definition
kotlin-test.mddescription: Enforce TDD workflow for Kotlin. Write Kotest tests first, then implement. Verify 80%+ coverage with Kover.
Kotlin TDD Command
This command enforces test-driven development methodology for Kotlin code using Kotest, MockK, and Kover.
What This Command Does
1. **Define Types/Interfaces**: Scaffold function signatures first 2. **Write Kotest Tests**: Create comprehensive test specs (RED) 3. **Run Tests**: Verify tests fail for the right reason 4. **Implement Code**: Write minimal code to pass (GREEN) 5. **Refactor**: Improve while keeping tests green 6. **Check Coverage**: Ensure 80%+ coverage with Kover
When to Use
Use `/kotlin-test` when:
- Implementing new Kotlin functions or classes
- Adding test coverage to existing Kotlin code
- Fixing bugs (write failing test first)
- Building critical business logic
- Learning TDD workflow in Kotlin
TDD Cycle
RED -> Write failing Kotest test
GREEN -> Implement minimal code to pass
REFACTOR -> Improve code, tests stay green
REPEAT -> Next test case
Example Session
User: /kotlin-test I need a function to validate user registration requests
Agent:
# TDD Session: Registration Validator
## Step 1: Define Interface
```kotlin
// validator/RegistrationValidator.kt
package com.example.validator
data class RegistrationRequest(
val name: String,
val email: String,
val password: String,
)
sealed class ValidationResult {
data object Valid : ValidationResult()
data class Invalid(val errors: List<String>) : ValidationResult()
}
fun validateRegistration(request: RegistrationRequest): ValidationResult {
TODO("not implemented")
}Step 2: Write Kotest Tests (RED)
// validator/RegistrationValidatorTest.kt
package com.example.validator
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.shouldBeInstanceOf
class RegistrationValidatorTest : FunSpec({
test("valid registration returns Valid") {
val request = RegistrationRequest(
name = "Alice",
email = "alice@example.com",
password = "SecureP@ss1",
)
val result = validateRegistration(request)
result.shouldBeInstanceOf<ValidationResult.Valid>()
}
test("blank name returns Invalid") {
val request = RegistrationRequest(
name = "",
email = "alice@example.com",
password = "SecureP@ss1",
)
val result = validateRegistration(request)
val invalid = result.shouldBeInstanceOf<ValidationResult.Invalid>()
invalid.errors shouldBe listOf("Name is required")
}
test("invalid email returns Invalid") {
val request = RegistrationRequest(
name = "Alice",
email = "not-an-email",
password = "SecureP@ss1",
)
val result = validateRegistration(request)
val invalid = result.shouldBeInstanceOf<ValidationResult.Invalid>()
invalid.errors shouldBe listOf("Invalid email format")
}
test("short password returns Invalid") {
val request = RegistrationRequest(
name = "Alice",
email = "alice@example.com",
password = "short",
)
val result = validateRegistration(request)
val invalid = result.shouldBeInstanceOf<ValidationResult.Invalid>()
invalid.errors shouldBe listOf("Password must be at least 8 characters")
}
test("multiple errors returns all errors") {
val request = RegistrationRequest(
name = "",
email = "bad",
password = "short",
)
val result = validateRegistration(request)
val invalid = result.shouldBeInstanceOf<ValidationResult.Invalid>()
invalid.errors.size shouldBe 3
}
})Step 3: Run Tests - Verify FAIL
$ ./gradlew test
RegistrationValidatorTest > valid registration returns Valid FAILED
kotlin.NotImplementedError: An operation is not implemented
FAILED (5 tests, 0 passed, 5 failed)
✓ Tests fail as expected (NotImplementedError).
Step 4: Implement Minimal Code (GREEN)
// validator/RegistrationValidator.kt
package com.example.validator
private val EMAIL_REGEX = Regex("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$")
private const val MIN_PASSWORD_LENGTH = 8
fun validateRegistration(request: RegistrationRequest): ValidationResult {
val errors = buildList {
if (request.name.isBlank()) add("Name is required")
if (!EMAIL_REGEX.matches(request.email)) add("Invalid email format")
if (request.password.length < MIN_PASSWORD_LENGTH) add("Password must be at least $MIN_PASSWORD_LENGTH characters")
}
return if (errors.isEmpty()) ValidationResult.Valid
else ValidationResult.Invalid(errors)
}Step 5: Run Tests - Verify PASS
$ ./gradlew test
RegistrationValidatorTest > valid registration returns Valid PASSED
RegistrationValidatorTest > blank name returns Invalid PASSED
RegistrationValidatorTest > invalid email returns Invalid PASSED
RegistrationValidatorTest > short password returns Invalid PASSED
RegistrationValidatorTest > multiple errors returns all errors PASSED
PASSED (5 tests, 5 passed, 0 failed)
✓ All tests passing!
Step 6: Check Coverage
$ ./gradlew koverHtmlReport
Coverage: 100.0% of statements
✓ Coverage: 100%
TDD Complete!
## Test Patterns
### StringSpec (Simplest)
```kotlin
class CalculatorTest : StringSpec({
"add two positive numbers" {
Calculator.add(2, 3) shouldBe 5
}
})BehaviorSpec (BDD)
class OrderServiceTest : BehaviorSpec({
Given("a valid order") {
When("placed") {
Then("should be confirmed") { /* ... */ }
}
}
})Data-Driven Tests
class ParserTest : FunSpec({
context("valid inputs") {
withData("2026-01-15", "2026-12-31"Read more
description: Enforce TDD workflow for Kotlin. Write Kotest tests first, then implement. Verify 80%+ coverage with Kover.
Kotlin TDD Command
This command enforces test-driven development methodology for Kotlin code using Kotest, MockK, and Kover.
What This Command Does
1. **Define Types/Interfaces**: Scaffold function signatures first 2. **Write Kotest Tests**: Create comprehensive test specs (RED) 3. **Run Tests**: Verify tests fail for the right reason 4. **Implement Code**: Write minimal code to pass (GREEN) 5. **Refactor**: Improve while keeping tests green 6. **Check Coverage**: Ensure 80%+ coverage with Kover
When to Use
Use `/kotlin-test` when:
- Implementing new Kotlin functions or classes
- Adding test coverage to existing Kotlin code
- Fixing bugs (write failing test first)
- Building critical business logic
- Learning TDD workflow in Kotlin
TDD Cycle
RED -> Write failing Kotest test GREEN -> Implement minimal code to pass REFACTOR -> Improve code, tests stay green REPEAT -> Next test case
Example Session
User: /kotlin-test I need a function to validate user registration requests
Agent:
# TDD Session: Registration Validator
## Step 1: Define Interface
```kotlin
// validator/RegistrationValidator.kt
package com.example.validator
data class RegistrationRequest(
val name: String,
val email: String,
val password: String,
)
sealed class ValidationResult {
data object Valid : ValidationResult()
data class Invalid(val errors: List<String>) : ValidationResult()
}
fun validateRegistration(request: RegistrationRequest): ValidationResult {
TODO("not implemented")
}Step 2: Write Kotest Tests (RED)
// validator/RegistrationValidatorTest.kt
package com.example.validator
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.shouldBeInstanceOf
class RegistrationValidatorTest : FunSpec({
test("valid registration returns Valid") {
val request = RegistrationRequest(
name = "Alice",
email = "alice@example.com",
password = "SecureP@ss1",
)
val result = validateRegistration(request)
result.shouldBeInstanceOf<ValidationResult.Valid>()
}
test("blank name returns Invalid") {
val request = RegistrationRequest(
name = "",
email = "alice@example.com",
password = "SecureP@ss1",
)
val result = validateRegistration(request)
val invalid = result.shouldBeInstanceOf<ValidationResult.Invalid>()
invalid.errors shouldBe listOf("Name is required")
}
test("invalid email returns Invalid") {
val request = RegistrationRequest(
name = "Alice",
email = "not-an-email",
password = "SecureP@ss1",
)
val result = validateRegistration(request)
val invalid = result.shouldBeInstanceOf<ValidationResult.Invalid>()
invalid.errors shouldBe listOf("Invalid email format")
}
test("short password returns Invalid") {
val request = RegistrationRequest(
name = "Alice",
email = "alice@example.com",
password = "short",
)
val result = validateRegistration(request)
val invalid = result.shouldBeInstanceOf<ValidationResult.Invalid>()
invalid.errors shouldBe listOf("Password must be at least 8 characters")
}
test("multiple errors returns all errors") {
val request = RegistrationRequest(
name = "",
email = "bad",
password = "short",
)
val result = validateRegistration(request)
val invalid = result.shouldBeInstanceOf<ValidationResult.Invalid>()
invalid.errors.size shouldBe 3
}
})Step 3: Run Tests - Verify FAIL
$ ./gradlew test RegistrationValidatorTest > valid registration returns Valid FAILED kotlin.NotImplementedError: An operation is not implemented FAILED (5 tests, 0 passed, 5 failed)
✓ Tests fail as expected (NotImplementedError).
Step 4: Implement Minimal Code (GREEN)
// validator/RegistrationValidator.kt
package com.example.validator
private val EMAIL_REGEX = Regex("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$")
private const val MIN_PASSWORD_LENGTH = 8
fun validateRegistration(request: RegistrationRequest): ValidationResult {
val errors = buildList {
if (request.name.isBlank()) add("Name is required")
if (!EMAIL_REGEX.matches(request.email)) add("Invalid email format")
if (request.password.length < MIN_PASSWORD_LENGTH) add("Password must be at least $MIN_PASSWORD_LENGTH characters")
}
return if (errors.isEmpty()) ValidationResult.Valid
else ValidationResult.Invalid(errors)
}Step 5: Run Tests - Verify PASS
$ ./gradlew test RegistrationValidatorTest > valid registration returns Valid PASSED RegistrationValidatorTest > blank name returns Invalid PASSED RegistrationValidatorTest > invalid email returns Invalid PASSED RegistrationValidatorTest > short password returns Invalid PASSED RegistrationValidatorTest > multiple errors returns all errors PASSED PASSED (5 tests, 5 passed, 0 failed)
✓ All tests passing!
Step 6: Check Coverage
$ ./gradlew koverHtmlReport Coverage: 100.0% of statements
✓ Coverage: 100%
TDD Complete!
## Test Patterns
### StringSpec (Simplest)
```kotlin
class CalculatorTest : StringSpec({
"add two positive numbers" {
Calculator.add(2, 3) shouldBe 5
}
})BehaviorSpec (BDD)
class OrderServiceTest : BehaviorSpec({
Given("a valid order") {
When("placed") {
Then("should be confirmed") { /* ... */ }
}
}
})Data-Driven Tests
class ParserTest : FunSpec({
context("valid inputs") {
withData("2026-01-15", "2026-12-31"Your agent can write code, but ECC gives it a coordinated engineering system and toolbox: it plans before it builds, verifies changes with tests, reviews its own work from a fresh context, remembers what matters, and turns repeated wins into reusable skills
Repo: affaan-m/everything-claude-code
Other commands on ecc.
- /add-language-rules
Workflow command scaffold for add-language-rules in everything-claude-code.
Open command - /database-migration
Workflow command scaffold for database-migration in everything-claude-code.
Open command - /feature-development
Workflow command scaffold for feature-development in everything-claude-code.
Open command - /aside
Answer a quick side question without interrupting or losing context from the current task. Resume work automatically after answering.
Open command - /auto-update
Pull the latest ECC repo changes and reinstall the current managed targets.
Open command - /build-fix
Detect the project build system and incrementally fix build/type errors with minimal safe changes.
Open command

