Testing
April 24, 2026 · View on GitHub
Actionbase is codifying its test conventions gradually. At this stage we commit to one rule; more patterns will be added later.
Data-Driven Test (@ObjectSource)
If your test is a table of input and expected output — input on the left,
expected on the right — use @ObjectSource with YAML. Each case is data,
not code: intent is readable from the YAML alone, and adding a case is a
data edit. Do not use @CsvSource or @ValueSource.
Good fits: parsers, validators, mappers, serializers — anywhere the test
body reduces to "compute actual from input, assert against expected".
import com.kakao.actionbase.test.documentations.params.ObjectSource
import com.kakao.actionbase.test.documentations.params.ObjectSourceParameterizedTest
@ObjectSourceParameterizedTest
@ObjectSource(
"""
- uri: datastore://my_namespace/my_table
namespace: my_namespace
table: my_table
- uri: datastore:///my_table
namespace: ""
table: my_table
- uri: datastore://ns/t
namespace: ns
table: t
""",
)
fun `valid URI`(uri: String, namespace: String, table: String) {
val (ns, tbl) = DatastoreUri.parse(uri)
assertEquals(namespace, ns)
assertEquals(table, tbl)
}
- YAML fields map to method parameters by name (Jackson binds them). Each case becomes its own JUnit invocation, so a failure points at one offending case.
- Infrastructure lives in
core/src/testFixtures/kotlin/com/kakao/actionbase/test/documentations/params/. - Escape hatch:
@ParameterizedTest+@MethodSource— only when cases must be generated at runtime. - See
DatastoreUriTest,V3NameValidatorTest,ObjectSourceTestfor more patterns (shared fields, nested cases, JSON block scalars).
Dense matrices (@TableSource)
When a test is a table of primitive values with many columns (state
transitions, combinatorial matrices), the repeated YAML keys of
@ObjectSource hurt density. Use @TableSource instead — columns declares
parameter names once, rows carries one test case per list:
@ObjectSourceParameterizedTest
@TableSource("""
columns: [from, event, expected]
rows:
- [IDLE, START, RUNNING]
- [RUNNING, STOP, IDLE]
""")
fun `transition`(from: State, event: Event, expected: State) { ... }
Still pure YAML. Same runner (@ObjectSourceParameterizedTest) and same
name-based parameter binding. Use ~ for null entries. For nested or
heterogeneous cases, prefer @ObjectSource.
Other tests
Write whatever is clearest for the case at hand.
Naming and assertions
- Class:
XxxTest. - Method: backtick sentence —
`should do X when Y`. - Kotlin:
kotlin.test.*. Java:org.junit.jupiter.api.Assertions.*.
Running
./gradlew test
./gradlew :engine:test --tests '*MutationServiceTest'
See CONTRIBUTING.md for the broader workflow.