In Kotest, how do you choose which test-layout style your test file uses, and name the four common spec styles?
answer
- No @Test — extend a base class
- StringSpec, FunSpec, DescribeSpec, BehaviorSpec
- Style = base class, not annotation
- init { } or constructor lambda
- Same matchers/lifecycle, different layout
basics
~10 sYou pick a style by which class your test class extends. Common ones are StringSpec, FunSpec, DescribeSpec, and BehaviorSpec. Each just changes how you write and group your tests.
solid answer
~30 sKotest has no @Test annotation. Instead, your test class extends a base spec class, and that base class dictates the DSL you write tests in. The four common styles are: `StringSpec` (a string literal followed by a lambda), `FunSpec` (calls to `test("...") { }`, groupable with `context("...")`), `DescribeSpec` (`describe`/`it`, RSpec-like, nestable), and `BehaviorSpec` (`given`/`when`/`then` BDD blocks, often `Given`/`When`/`Then`). You typically put your test bodies inside an `init { }` block (StringSpec/BehaviorSpec) or directly in lambdas (FunSpec/DescribeSpec). All styles share the same matchers, lifecycle callbacks, and config — only the layout differs, so the choice is about readability/team convention, not capability.
go deeper
Can name the styles and state that the base class chooses the layout, not an annotation.
Explains init-block vs constructor-lambda registration and that all styles share engine/matchers.
Discusses per-class choice, team conventions, and mapping styles to test types (unit vs BDD acceptance).
Frames style selection as a consistency/maintainability governance decision and standardizes it across the codebase.
## The core idea Unlike JUnit, Kotest does not mark tests with an annotation like `@Test`. Instead **the test layout/style is selected by the base class your test class extends**. Switching `class MyTest : StringSpec()` to `class MyTest : FunSpec()` changes the DSL you write tests with. All styles compile to the same engine and support the same matchers, lifecycle hooks, and per-test config — only the *syntax for declaring and nesting tests* differs. ## The four common styles - **StringSpec** — the most minimal. A string literal is the test name, followed by a lambda body. No nesting. - **FunSpec** — tests are declared with `test("name") { }`; group with `context("name") { }`. - **DescribeSpec** — RSpec/Jest-like: `describe("...") { it("...") { } }`, freely nestable. - **BehaviorSpec** — BDD: `given("...") { `when`("...") { then("...") { } } }` (capitalized `Given`/`When`/`Then` aliases exist to avoid the `when` keyword backtick). ## Where the test bodies go Some styles declare tests in an `init { }` block (StringSpec, BehaviorSpec, WordSpec); others (FunSpec, DescribeSpec) accept a lambda passed to the constructor. Both are valid — Kotest registers tests at construction time. ```kotlin import io.kotest.core.spec.style.StringSpec import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe class StringStyle : StringSpec({ "1 + 1 should be 2" { (1 + 1) shouldBe 2 } }) class FunStyle : FunSpec({ context("addition") { test("1 + 1 is 2") { (1 + 1) shouldBe 2 } } }) ``` ## Why it matters The spec style is a **per-class** decision; different test classes in the same project can use different styles. Teams usually standardize on one or two (e.g. FunSpec for unit, BehaviorSpec for BDD acceptance tests) for consistency.
- Can two test classes in the same module use different spec styles?Yes. Style is a per-class choice driven by the base class, so you can freely mix StringSpec and BehaviorSpec across files.
- Does the spec style affect which matchers you can use?No. Matchers (e.g. shouldBe) are independent of style; every style uses the same matcher library.
Choosing a spec style is like choosing a notebook template: lined, dotted, or grid — the paper (engine) is the same; only the layout you write on differs.
saying these in an interview costs you the question
- Claiming Kotest tests use a @Test annotation like JUnit
- Saying the style determines which assertions/matchers are available
- Thinking you must use one style across the whole project
- Confusing spec style with the test framework choice itself