Skip to main content

Configuration

Kensa is configured once, before your tests run. There are two styles — a Kotlin DSL and a fluent Java-friendly builder.

Entry Points

// DSL style — preferred in Kotlin
Kensa.konfigure {
outputDir = Path("build/kensa-output")
issueTrackerUrl = URI("https://github.com/my-org/my-repo/issues/").toURL()
}

Configuration is typically placed in a test base class, a JUnit 5 @BeforeAll, or a Kotest ProjectConfig.


Output

Builder methodDSL propertyTypeDefaultDescription
withOutputDir(path)outputDirPathsystem temp dir / kensa-outputWhere HTML reports are written. The builder method requires an absolute path and appends a kensa-output leaf unless the path already ends with one; the DSL property assigns the path exactly as given
withOutputDisabled()isOutputEnabled = falseBooleantrueSuppress all report generation
withFlattenOutputPackages(bool)flattenOutputPackagesBooleanfalseSimplify package paths in output filenames
withPackageDisplayMode(mode)packageDisplayPackageDisplayHideCommonPackagesHow package names appear in the report
withPackageDisplayRoot(root)packageDisplayRootString?nullRoot package to strip when displaying package names

System properties override defaults before configuration is applied:

PropertyEffect
kensa.output.rootOverrides the output directory root
kensa.disable.outputSet to any value to disable output
Kensa.konfigure {
outputDir = Path("build/kensa-output")
packageDisplay = PackageDisplay.HideCommonPackages
}

Issue Tracker

Annotate tests with @Issue("PROJ-123") and Kensa will link to the issue in the report. Set the base URL here:

Builder methodDSL propertyTypeDescription
withIssueTrackerUrl(url)issueTrackerUrlURLBase URL — issue keys are appended directly
Kensa.konfigure {
issueTrackerUrl = URI("https://github.com/my-org/my-repo/issues/").toURL()
}

With the above URL, @Issue("42") links to https://github.com/my-org/my-repo/issues/42.


Report Layout

Builder methodDSL propertyTypeDefaultDescription
withSectionOrder(vararg sections)sectionOrderList<Section>[Tabs, Sentences, Exception]Order of report sections
withAutoOpenTab(tab)autoOpenTabTabTab.NoneWhich tab is open by default
withAutoExpandNotes(bool)autoExpandNotesBooleanfalseExpand @Notes content automatically
withTabSize(n)tabSizeInt4Code indentation width
withSetupStrategy(strategy)setupStrategySetupStrategySetupStrategy.UngroupedHow setup interactions appear in sequence diagrams

Section values: Tabs, Sentences, Exception

Tab values: CapturedInteractions, CapturedOutputs, Parameters, SequenceDiagram, None

SetupStrategy values:

ValueEffect
UngroupedSetup interactions shown inline, not grouped
GroupedSetup interactions grouped into a labelled box
IgnoredSetup interactions hidden from the sequence diagram

Sentence Parsing

Kensa parses method names to build readable sentences. Extend the dictionary to handle domain-specific terms:

Builder methodDescription
withProtectedPhrases(vararg phrases)Prevent a multi-word phrase from being split (e.g. "credit score")
withAcronyms(vararg acronyms)Register an acronym and its meaning (e.g. Acronym.of("API", "Application Programming Interface"))
withKeywords(vararg keywords)Add custom BDD keywords beyond the defaults
Kensa.konfigure {
protectedPhrases(ProtectedPhrase("credit score"))
acronyms(Acronym.of("API", "Application Programming Interface"))
}

Custom Renderers

Register custom value or interaction renderers for types Kensa doesn't know how to display:

Builder methodDescription
withValueRenderer(klass, renderer)Custom ValueRenderer<T> for a specific type
withInteractionRenderer(klass, renderer)Custom InteractionRenderer<T> for sequence diagram content
withListRendererFormat(format)Override the default [a, b, c] list format
Kensa.configure()
.withValueRenderer(Money::class, MoneyRenderer())
.withListRendererFormat(ListRendererFormat(separator = " | ", prefix = "(", postfix = ")"))

// Or using the DSL extension:
Kensa.konfigure {
withRenderers {
valueRenderer<Money> { money -> "${money.currency} ${money.amount}" }
}
}

Sequence Diagrams

Configure how participants are declared and rendered in the sequence diagram. Declaration order in the sequenceDiagram { } block is the left-to-right order on the rendered diagram.

Kensa.konfigure {
sequenceDiagram {
title("Order placement")
actor("User")
participant("Frontend")
box("Backend") {
participant("Orchestration")
database("OrderStore")
}
queue("Events")
hideUnlinked()
}
}

Participants

Eight participant kinds — each maps directly to a PlantUML participant type:

DSL methodPlantUML output
participant(name)participant name
actor(name)actor name
boundary(name)boundary name
control(name)control name
entity(name)entity name
database(name)database name
collections(name)collections name
queue(name)queue name

Each call returns a handle. Chain .withColour(...) and .withAlias(...) inline to style or re-label the participant:

sequenceDiagram {
actor("Operations").withColour("#LightBlue").withAlias("Ops")
participant("Orchestration")
}

A Party overload is provided for each method — if your test suite already defines Party constants, pass them directly: participant(MyParty.Orchestration).

Boxes

Group related participants under a labelled box. The box is rendered around the listed participants:

sequenceDiagram {
box("Backend", colour = "#LightYellow") {
participant("Orchestration")
database("OrderStore")
}
}

Nested boxes are not supported. Use sibling boxes at the top level.

Title & Hide Unlinked

sequenceDiagram {
title("Order placement", "Happy path")
actor("User")
participant("Unused")
hideUnlinked() // omits participants that have no interactions
}

Primary Participant

Mark a participant as primary to pin it as the leftmost participant in the diagram and to guarantee it is rendered even when a test captures only a divider (SD-MARKER value such as ==Setup==) or no interactions at all — situations where PlantUML would otherwise fail to recognise the markup.

sequenceDiagram {
primary.actor("SUT").withColour("#LightGreen")
participant("OrderService")
database("Ledger")
}

The primary is prepended to the participants emitted in the diagram, so a single declaration is enough — no need to also list the same name via participant("SUT"). If you do declare a participant with the same name elsewhere (top level or inside a box { }), the primary is suppressed so it is not double-emitted; your explicit declaration wins (and keeps its position).

primary.<type>(name) accepts the same eight participant kinds as the top-level methods and returns the same handle for .withColour(...) / .withAlias(...) chaining. Setting primary twice overwrites the previous value — only one primary is honoured.

Replacement Semantics

Each sequenceDiagram { } block resets the prior configuration before applying its body:

Kensa.konfigure {
sequenceDiagram { participant("Alpha") }
sequenceDiagram { participant("Bravo") } // Alpha is discarded
}

This matches the replacement behaviour of the deprecated umlDirectives = listOf(...) setter.


Source Locations

If you use @Sources to parse helper classes referenced in tests, tell Kensa where to find source files:

Builder methodDSL propertyTypeDescription
withSourceLocations(vararg paths)sourceLocationsList<Path>Paths to scan for .kt / .java source files
Kensa.konfigure {
sourceLocations = listOf(Path("src/test/kotlin"))
}