RSpec/Mocha/Vitest-style output for Kotlin that works with Kotest's
DescribeSpec by integrating as a real Gradle plugin. It hooks Gradle's
own TestListener API directly, so every Test task gets the tree
renderer automatically. Pick the style that reads best for your team once,
then leave it.
Published and approved on the Gradle Plugin Portal:
plugins {
id("com.netpress.kotidy") version "0.1.0"
}with gradlePluginPortal() in your pluginManagement.repositories. That's
it -- every Test task in the project gets the tree renderer
automatically, no further wiring needed.
kotidy {
style = "fd" // classic (default), fd, fs, or fv
}Or override at runtime without touching build.gradle.kts:
./gradlew test -Dkotidy.style=fd
Four named styles:
style |
Convention | Look |
|---|---|---|
classic (default) |
Our base formatter | Glyph + name (N seconds), failures add (FAILED - N) |
fd |
RSpec's doc format | Plain colored name, yellow (PENDING) for skips |
fs |
Mocha's spec format | Green ✔ + gray name, red ✗ name (FAILED - N) |
fv |
Vitest's own tree | Green ✓ name, two-toned green 2ms, red × name, dim gray ↓ name |
The first three end with a verdict + counts footer (Test Succeeded/
Tests Passed: 0 failed, 0 skipped, 45 total (0.057 seconds)); fv ends
with Vitest's own Test Files/Tests/Duration footer instead,
right-justified the same way. Test Files counts distinct top-level spec
classes.
Two real candidates exist on the Gradle side, and neither covers this gap:
gradle-test-logger-plugin
gives real nested indentation with checkmarks via its mocha theme, but
inserts a blank line between every describe/context group with no
config flag to disable it -- confirmed still true as of its current README.
It also has no RSpec-doc-style (no-glyph) or Vitest-tree equivalent.
kotest-gradle-plugin
(io.kotest, alpha) solves a different problem: Gradle's own JUnit Platform
integration flattens nested Kotest names to leaf-only in its build output and
reports, and this plugin replaces the whole test-running task (its own
kotest task, not test) to recover the real names. It doesn't offer style
switching, and swapping the test task itself is a bigger commitment than a
TestListener add-on.
kotidy's own formatting logic (Styles.kt) has no Gradle API dependency --
it's tested directly with Kotest's DescribeSpec, using the same
describe/context/it structure and a subject/beforeEach pattern for
shared setup. KotidyPlugin.kt itself (the TestListener wiring) isn't
unit-tested the same way -- verifying it means actually applying the plugin
in a consuming project and reading real console output. For how we write
those Kotest specs more generally -- context nesting, the subject pattern,
mocking and stubbing -- see docs/FRAMEWORK.md.
- Tree order follows completion order, which matches declaration order for serial tests but can reorder under parallel test execution.
fv's per-leaf millisecond timing is only as precise as Gradle's ownTestResultstart/end timestamps -- sub-millisecond tests will round.make build/test/checkrender kotidy's own suite with Gradle's plain default output, not kotidy's own tree -- applying the plugin to its own in-progress build isn't possible mid-compile.make dogfoodapplies the last-published Portal version instead, just to capturedocs/example.png.
make build # ./gradlew ktlintFormat && ./gradlew build -x test
make test # ./gradlew ktlintFormat && ./gradlew clean test
make lint # ./gradlew ktlintCheck
make check # ./gradlew ktlintFormat && ./gradlew clean check
make dogfood # ./gradlew clean test -Pdogfood -- renders this repo's own
# suite through the last-published Portal version, for
# docs/example.png only (see "Limitations" above)