`gitTally` is the name of another product in the git space, so the rename is a precaution; nothing about what the build system does changes. The name follows one rule: `Werkator` where it is prose, capitalized where it is a Kotlin type and its file, lowercase everywhere a machine reads it — the command, packages, paths, configuration keys and values, the Gitea check context. Environment variables keep their convention and are uppercase throughout. Every configuration file is still found under its pre-rename name (`ConfigFiles`): `.gittally.yml` at the repository root, in a build worktree and as committed on a branch, `.git/gittally/.gittally.yml` for the machine layer. The current name wins where both exist, and the old file is then ignored rather than merged — two files side by side are a half-done rename, not a layering. Without the fallback an installation that updated without renaming would not fail: a configuration that is not found leaves every setting at its default, so it would come up looking healthy while having forgotten its credentials and its builds. `docs/werkator-migrationsplan.md` lists what the fallback does not cover and has to be moved by hand — above all the state directory `.git/werkator/`, which holds the build history, the control token and the worktrees, and has no fallback of its own. `docs/migration-from-legacy.md` is deleted with this: it mapped the legacy script's environment variables, and every host it addressed has long since moved to the YAML configuration. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
94 lines
3.9 KiB
Markdown
94 lines
3.9 KiB
Markdown
# Test Framework Selection
|
|
|
|
**Status:**
|
|
- proposed: 2026-06-09
|
|
- accepted: 2026-06-09
|
|
- rejected: -
|
|
- superseded: -
|
|
|
|
**Decision [accepted]:** Kotest — Kotlin-native test runner with richer DSL than JUnit 5; paired with MockK, WireMock, and Testcontainers.
|
|
|
|
## Context and Problem Statement
|
|
|
|
Werkator is a greenfield Kotlin/Spring Boot project.
|
|
A test framework must be chosen before writing any tests.
|
|
|
|
The framework shapes how tests are structured, how readable they are, and how well they integrate with the Spring Boot test slice infrastructure.
|
|
|
|
### Technical Background
|
|
|
|
The JVM test ecosystem offers multiple runners for Kotlin projects.
|
|
The main candidates are
|
|
- [JUnit 5](https://junit.org/junit5/) (the de-facto standard on the JVM),
|
|
- [Kotest](https://kotest.io/) (a Kotlin-native framework built on the JUnit 5 platform),
|
|
- and [Spek 2](https://www.spekframework.org/) (a Kotlin BDD framework).
|
|
|
|
- All three can coexist with [MockK](https://mockk.io/) for mocking and [WireMock](https://wiremock.org/) / [Testcontainers](https://testcontainers.com/) for integration-level stubs.
|
|
|
|
## Considered Options
|
|
|
|
* [JUnit 5](https://junit.org/junit5/)
|
|
* [Kotest](https://kotest.io/)
|
|
* [Spek 2](https://www.spekframework.org/)
|
|
|
|
### [JUnit 5](https://junit.org/junit5/)
|
|
|
|
The standard JVM test runner, included transitively via `spring-boot-starter-test`.
|
|
|
|
#### Advantages
|
|
|
|
- Zero additional dependencies — already on the classpath.
|
|
- Universal IDE and tooling support.
|
|
- Extensive documentation and community resources.
|
|
- Native support for all Spring Boot test slices (`@SpringBootTest`, `@WebMvcTest`, etc.).
|
|
- No learning curve for developers already familiar with it.
|
|
|
|
#### Disadvantages
|
|
|
|
- Test structure is class-/method-based; nesting requires `@Nested` inner classes, which is verbose in Kotlin.
|
|
- Assertion style (`assertEquals`, `assertThrows`) is less expressive than Kotlin-idiomatic alternatives.
|
|
|
|
### [Kotest](https://kotest.io/)
|
|
|
|
A Kotlin-native test framework that runs on the JUnit 5 platform engine. Provides multiple spec styles (e.g. `DescribeSpec`, `BehaviorSpec`, `FunSpec`).
|
|
|
|
#### Advantages
|
|
|
|
- Expressive, Kotlin-idiomatic DSL with clean nesting — no `@Nested` boilerplate.
|
|
- Rich built-in assertion library (`shouldBe`, `shouldThrow`, etc.) with good error messages.
|
|
- Multiple spec styles allow choosing the right level of formality per test type.
|
|
- `kotest-extensions-spring` enables `@SpringBootTest` and all Spring slices natively.
|
|
- Pairs naturally with MockK (both are Kotlin-first).
|
|
- Actively maintained with a large community.
|
|
|
|
#### Disadvantages
|
|
|
|
- Additional dependency (`kotest-runner-junit5`, `kotest-assertions-core`, `kotest-extensions-spring`).
|
|
- Slightly steeper learning curve if the team is new to it.
|
|
- Spring context caching behavior requires awareness of how Kotest manages lifecycle.
|
|
|
|
### [Spek 2](https://www.spekframework.org/)
|
|
|
|
A Kotlin BDD framework with a `describe/it` DSL inspired by RSpec.
|
|
|
|
#### Advantages
|
|
|
|
- Clear BDD-style specification structure.
|
|
|
|
#### Disadvantages
|
|
|
|
- Development has stalled; no meaningful releases in several years.
|
|
- Spring Boot integration is not maintained.
|
|
- Smaller community; risk of abandonment.
|
|
|
|
## Decision Outcome
|
|
|
|
**[Kotest](https://kotest.io/)** is chosen as the primary test runner and assertion library, supplemented by [MockK](https://mockk.io/) for mocking, [WireMock](https://wiremock.org/) for HTTP stubbing (Gitea API), and [Testcontainers](https://testcontainers.com/) for Docker-based integration tests.
|
|
|
|
The main reasons:
|
|
|
|
- Kotest's nested DSL fits Kotlin's concise style better than `@Nested` inner classes, and its assertion library produces clearer failure messages. The Spring extension covers all Spring Boot test slices, so there is no capability regression compared to JUnit 5. The additional dependency cost is low.
|
|
- Spek 2 is excluded due to its abandoned state.
|
|
|
|
JUnit 5 remains on the classpath (as a transitive dependency and as Kotest's engine), so any JUnit 5 tests can coexist if needed.
|