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-reports")
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
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-reports")
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, Givens, 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("API", "Application Programming Interface"))
withKeywords(vararg keywords)Add custom BDD keywords beyond the defaults
Kensa.configure()
.withProtectedPhrases(ProtectedPhrase("credit score"))
.withAcronyms(Acronym("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"))
}