Files
werkator/.claude/skills/writing-tests/SKILL.md
mhoennigandClaude Opus 5 35f06ec1ec Rename GitTally to Werkator
`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>
2026-08-30 19:39:55 +02:00

2.1 KiB

name, description
name description
writing-tests Werkator testing conventions — Kotest FunSpec spec structure, MockK matchers, and the two patterns for mocking beans in Spring slice tests (springmockk @MockkBean or @TestConfiguration). Use when writing, extending, or refactoring tests.

Writing Tests for Werkator

Tests use Kotest FunSpec style. SpringExtension is registered globally in io.kotest.provided.ProjectConfig — do not add it per-spec.

class MyTest : FunSpec() {
    init {
        test("description") { ... }
        beforeEach { ... }
    }
}

Use shouldBe, shouldNotBe, shouldThrow etc. from io.kotest.matchers.

Tests mirror the production package structure under src/test/kotlin.

Run a single test class instead of the full suite while iterating:

./gradlew test --tests "de.hoennig.werkator.ApplicationContextTest"

Mocking in Spring Slice Tests

Use @MockkBean from springmockk to inject MockK mocks into the Spring context:

@WebMvcTest(SomeController::class)
class SomeControllerTest : FunSpec() {
    @MockkBean
    lateinit var someService: SomeService
    init {
        beforeEach { clearMocks(someService) }
        // full MockK syntax: every { } / verify { }
    }
}

Alternatively, register mocks via @TestConfiguration without the springmockk dependency:

@WebMvcTest(SomeController::class)
@Import(SomeControllerTest.Mocks::class)
class SomeControllerTest : FunSpec() {
    @TestConfiguration
    class Mocks {
        @Bean fun someService(): SomeService = mockk()
    }
    @Autowired lateinit var someService: SomeService
    init {
        beforeEach { clearMocks(someService) }
    }
}

Pure unit tests (no Spring context) use MockK directly without any Spring wiring.

Test Infrastructure by Layer

  • Git-facing code: integration tests against local fixture repositories (bare origin + clones), see GitServiceTest — no network access, hermetic git environment variables.
  • HTTP clients (Gitea): WireMock.
  • Docker-dependent code: Testcontainers.
  • The Watcher and other schedulers never start their loops in tests; call poll()/lifecycle methods directly.