Architecture Baselines

When integrating architecture tests into large, established codebases, you will often encounter thousands of pre-existing violations. Forcing developers to fix all historical violations immediately is a massive blocker.

Konture solves this with Architecture Baselines, allowing you to record all existing violations to a baseline file, ignore them in subsequent runs, and focus entirely on preventing new architectural erosion!


πŸ“¦ Distributed Baselines

Unlike traditional architecture test frameworks that record violations into a single, massive monolithic baseline file at the project root (creating merge conflicts on every pull request), Konture features Distributed Baselines.

If your project is a multi-module workspace and you specify a relative baseline file name, Konture’s baseline engine (BaselineManager) automatically correlates recorded violations back to the submodules they originated from. It writes localized baseline files directly inside each submodule directory!

my-project/
β”œβ”€β”€ core/
β”‚   └── database/
β”‚       β”œβ”€β”€ src/
β”‚       └── konture-baseline.json   <-- Violations local to database module
β”œβ”€β”€ feature/
β”‚   └── payment/
β”‚       β”œβ”€β”€ src/
β”‚       └── konture-baseline.json   <-- Violations local to payment module
└── konture-test/

This isolates changes, completely prevents git merge conflicts on PRs, and makes ownership of technical debt crystal clear!


πŸƒ Generating & Committing Baselines

To establish your baseline and freeze existing technical debt:

Step 1: Run your tests in Generate Mode

You can run the built-in Gradle task registered by the Konture plugin, which automatically sets konture.baseline.generate=true and runs all test tasks:

./gradlew generateKontureBaseline

Or target a specific submodule to generate or update its baseline in isolation:

./gradlew :feature:payment:generateKontureBaseline

🐘 Gradle (Alternative Manual CLI Override)

You can also manually execute your test task while passing the generate flag as a JVM system property:

./gradlew :konture-test:test -Dkonture.baseline.generate=true

πŸ“¦ Maven

For Maven projects, pass the system property directly:

mvn test -pl konture-test -Dkonture.baseline.generate=true

Upon completion, Konture will succeed and automatically generate a localized konture-baseline.json file in each module containing structural violations.

Step 2: Commit baselines to Git

Commit the generated konture-baseline.json files to your version control repository alongside your tests:

git add **/konture-baseline.json
git commit -m "chore: freeze architecture violations baseline"

In subsequent standard test executions (without the generate flag), Konture will load these files, filter out the pre-existing violations, and pass. Any new violation introduced by developers will fail the build immediately!


βš™οΈ Baseline Configuration Reference

You can customize baseline behavior either programmatically on the Konture runtime or via JVM system properties.

Precedence Rules: JVM system properties always take precedence over programmatic properties configured via the Konture singleton runtime or Gradle DSL extension.

Programmatic Property System Property Default Value Description
Konture.baselinePath konture.baseline.path "konture-baseline.json" Path of the baseline files. Can also be set in Gradle via the konture { baselinePath("custom.json") } block. If relative, and a Gradle/Maven graph is present, it writes distributed baseline files in submodules.
Konture.generateBaseline konture.baseline.generate false When true, enables generate mode to write or update baseline files, pruning resolved violations and deleting empty baseline files.
Konture.reportResolvedViolations konture.reportResolvedViolations true When true, logs an informational message during test execution if baseline violations have been resolved.
Konture.failOnResolvedViolations konture.failOnResolvedViolations false Ratchet Mode. When true, fails test execution if any previously baselined violation is resolved, prompting developers to regenerate the baseline.
N/A konture.baseline.dir System property Overrides the target output directory for baseline files (see below for absolute-path check behavior).

πŸ“ˆ Technical Debt Tracking & Delta Baselines

Konture computes violation deltas during test execution:

  • Active Baseline Violations: Violations present in both the baseline and current codebase ($V_{\text{evaluated}} \cap V_{\text{baseline}}$).
  • New Violations: Newly introduced violations that are not in the baseline ($V_{\text{evaluated}} \setminus V_{\text{baseline}}$). These fail your build.
  • Resolved Violations: Violations that were in the baseline but are now fixed in the codebase ($V_{\text{baseline}} \setminus V_{\text{evaluated}}$).

Technical debt metrics are automatically included in test summary logs and JSON/HTML/SARIF reports under reportSummary:

{
  "summary": {
    "totalViolations": 1,
    "activeBaselineCount": 1,
    "resolvedCount": 2,
    "newViolationsCount": 0
  }
}

πŸ”’ Ratchet Mode (Prevent Regression of Fixed Debt)

When a developer refactors code and resolves existing architectural debt, you want to make sure new violations can never re-introduce that debt.

Enable Ratchet Mode to ensure baselines only shrink:

Gradle Configuration

konture {
    failOnResolvedViolations = true
}

CLI / CI Flag

./gradlew test -Dkonture.failOnResolvedViolations=true

When Ratchet Mode is enabled and resolved violations are detected, Konture fails the build with an actionable error:

Baseline contains 3 resolved violation(s) but failOnResolvedViolations is enabled. Please update baseline using ./gradlew generateKontureBaseline.

Programmatic Ratchet Verification in Tests

You can also invoke Konture.checkRatchet() directly within test suites (such as in a @AfterAll or test lifecycle listener) to fail the test suite immediately if resolved technical debt is detected:

@AfterAll
fun verifyRatchet() {
    Konture.checkRatchet()
}

Baseline Regeneration & Test Filtering: When regenerating baselines (-Dkonture.baseline.generate=true or ./gradlew generateKontureBaseline), ensure the full test suite runs without --tests filtering so all architecture rules across the project are evaluated before resolved violations are pruned.


πŸ“‹ JSON Baseline Schema

Baselines are serialized using kotlinx-serialization for speed and consistency. The schema maps violations down to specific test classes and methods, preventing a violation under one test from accidentally ignoring a different rule.

Schema Format

Konture supports a multi-class baseline schema, grouping all recorded violations under the testClasses block by their respective class and test/method:

{
  "version": 1,
  "testClasses": [
    {
      "name": "com.acme.konture.MyArchitectureTest",
      "tests": [
        {
          "name": "repositories should be interfaces",
          "violations": [
            {
              "location": ":database, main source set, com/acme/database/SomeRepository.kt:12",
              "message": "Class com.acme.database.SomeRepository must be declared as interface"
            }
          ]
        }
      ]
    },
    {
      "name": "com.acme.konture.OtherArchitectureTest",
      "tests": [
        {
          "name": "controllers should only depend on services",
          "violations": [
            {
              "location": ":web, main source set, com/acme/web/SomeController.kt:34",
              "message": "Class com.acme.web.SomeController depends on repository directly"
            }
          ]
        }
      ]
    }
  ]
}

πŸ”„ Regenerating Baselines After an Upgrade

Baseline entries are matched against the exact violation text a rule produces. When an upgrade improves the wording or location of violation messages, previously recorded entries no longer match and their violations resurface as if new.

After upgrading Konture, regenerate your baselines once and commit the result:

./gradlew generateKontureBaseline

This is a one-time step per upgrade that changes message formatting; it does not weaken any rule, it only refreshes the stored text.


This site uses Just the Docs, a documentation theme for Jekyll.