Links
Comment on page

Getting Started

The following example provides the minimum setup for writing a Konsist test.
Starter (preconfigured) projects containing Konsist tests are available here.

Add Repository

Add mavenCentral repository:
repositories {
mavenCentral()
}

Add Konsist Dependency

To use Konsist, include the Konsist dependency from Maven Central:
Gradle (Kotlin)
Gradle (Groovy)
Maven
More
Add the following dependency to the module\build.gradle.kts file:
dependencies {
testImplementation("com.lemonappdev:konsist:0.13.0")
}
Add the following dependency to the module\build.gradle file:
dependencies {
testImplementation "com.lemonappdev:konsist:0.13.0"
}
Add the following dependency to the module\pom.xml file:
<dependency>
<groupId>com.lemonappdev</groupId>
<artifactId>konsist</artifactId>
<version>0.13.0</version>
<scope>test</scope>
</dependency>
Dependency can be added to other build systems as well. Check the snippets section in the Sonatype repository.
To achieve better test separation Konsist can be configured inside a konsistTest source set or a dedicated module. See Isolate Konsist Tests.
At a high-level Konsist check is a Unit test following multiple implicit steps.
3 steps are required for a declaration check and 4 steps are required for an architecture check:
The declaration represents Kotlin declaration eg. Kotlin class is represented by KoClassDeclaration allowing to access class name (koClassDeclaration.name), methods (koClassDeclaration.functions()), etc. See Declaration.

Create The Scope

The first step is to get a list of Kotlin files to be verified. This step is common for declaration checks and architecture checks.
The Konsist object is an entry point to the Konsist framework. The scopeFromProject method obtains the instance of the scope containing all Kotlin project files present in the project:
Konsist.scopeFromProject() // Define the scope containing all Kotlin files present in the project
To define more granular scopes see the Create The Scope page.
The following sections will present how to use a scope by writing declaration checks and architecture checks.

Declaration Check

Let's write a simple test to verify that classes (class declarations) annotated with the RestController annotation resides in controller package.

Query and Filter Declarations

To write this declaration check query all classes present in the scope:
Konsist.scopeFromProject()
.classes() // Get scope classes
Perform additional filtering to get classes annotated with RestController annotation:
Konsist.scopeFromProject()
.classes()
.withAllAnnotationsOf(RestController::class) // Filter classes annotated with 'RestController'
To perform more advanced querying and filtering see the Declaration Query And Filterpage.

Assert

Assert is the final step to perform declaration verification - use assert combined with koClass.resideInPackage method to make sure that all classes (filtered in the previous step) reside in controller package:
Konsist.scopeFromProject()
.classes()
.withAllAnnotationsOf(RestController::class)
.assertTrue { it.resideInPackage("..controller") } // Define the assertion
To learn more about assertions see Declaration Assert page.
The double dot syntax (..) means zero or more packages - controller package preceded by any number of packages (seePackage Wildcard syntax).

Wrap Konsist Code In Test

The above code describes declaration consistency logic. To guard this logic (and ideally, check it with every Pull Request) it will be executed in the form of a test. Konsist code can be wrapped in the test using popular testing frameworks:
JUnit
Kotest
class ControllerClassKonsistTest {
@Test
fun `classes annotated with 'RestController' annotation reside in 'controller' package`() {
Konsist.scopeFromProject() // 1. Create a scope representing the whole project (all Kotlin files in project)
.classes() // 2. Get scope classes
.withAllAnnotationsOf(RestController::class) // 2. Filter classes annotated with 'RestController'
.assertTrue { it.resideInPackage("..controller..") } // 3. Define the assertion
}
}
The JUnit testing framework project dependency should be added to the project. See starter projects to get a complete sample project.
class ControllerClassKonsistTest : FreeSpec({
"classes annotated with 'RestController' annotation reside in 'controller' package" {
Konsist.scopeFromProject() // 1. Create a scope representing the whole project (all Kotlin files in project)
.classes() // 2. Get scope classes
.withAllAnnotationsOf(RestController::class) // 2. Filter classes annotated with 'RestController'
.assertTrue (
testName = this.testCase.name.testName
) {
it.resideInPackage("..controller..")
} // 3. Define the assertion
}
})
For Kotest to function correctly the Kotest test name has to be explicitly passed. See theKotest Support page.
The Kotest testing framework project dependency should be added to the project. See starter projects to get a complete sample project.
The above snippets present a complete example of a test verifying that all classes annotated with RestController annotation reside in the controller package. Since scope is created from all project files this test will verify existing and new classes.
Notice that test class has a KonsistTest suffix. This is the recommended approach to name Konsist tests.
Review the Snippets for more examples of declaration checks.
The above test will execute multiple assertions per test (all controllers will be verified in a single test). If you prefer better isolation each assertion can be executed as a separate test. See theDynamic Konsist Tests page.

Architectural Check

Let's write a simple test to verify that application architecture rules are preserved. In this scenario, the application follows a simple 3-layer architecture, where Presentation layer depends on Business layer and Business layer depends on Data layer. The Data layer has no layer dependencies:

Assert Architecture

Use assertArchiteture method combined with architecture definition to make sure that all classes meet architectural criteria:
Konsist
.scopeFromProject()
.assertArchitecture { // Assert architecture
}

Define Layers

Create layers instances to represent project layers. Each Layer instance accepts the name (used for presenting architecture violation errors) and package used to define layers.
Konsist
.scopeFromProject()
.assertArchitecture {
// Define layers
private val presentation = Layer("Presentation", "com.myapp.presentation..")
private val business = Layer("Business", "com.myapp.business..")
private val data = Layer("Data", "com.myapp.data..")
}
The presence of two dots at the end signifies that the layer is encompassed by the com.myapp.business package along with its sub-packages.

Define Architecture Assertions

The final step is to define the relations between each layer:
Konsist
.scopeFromProject()
.assertArchitecture {
private val presentation = Layer("Presentation", "com.myapp.presentation..")
private val business = Layer("Business", "com.myapp.business..")
private val data = Layer("Data", "com.myapp.data..")
// Define architecture assertions
presentation.dependsOn(business)
business.dependsOn(data)
data.dependsOnNothing()
}

Wrap Konsist Code In Test

The above code describes architecture consistency logic. Same as with the declaration check this logic should be executed as a unit test using you preferred testing framework:
JUnit
Kotest
class ArchitectureKonsistTest {
@Test
fun `architecture layers have dependencies correct`() {
Konsist
.scopeFromProject() // Define the scope containing all Kotlin files present i
.assertArchitecture { // Assert architecture
// Define layers
private val presentation = Layer("Presentation", "com.myapp.presentation..")
private val business = Layer("Business", "com.myapp.business..")
private val data = Layer("Data", "com.myapp.data..")
// Define architecture assertions
presentation.dependsOn(business)
business.dependsOn(data)
data.dependsOnNothing()
}
}
}
The JUnit testing framework project dependency should be added to the project. See starter projects to get a complete sample project.
class ArchitectureKonsistTest {
class UseCaseTest : FreeSpec({
"architecture layers have dependencies correct" {
Konsist
.scopeFromProject() // Define the scope containing all Kotlin files present i
.assertArchitecture() { // Assert architecture
// Define layers
val presentation = Layer("Presentation", "com.myapp.presentation..")
val business = Layer("Business", "com.myapp.business..")
val data = Layer("Data", "com.myapp.data..")
// Define architecture assertions
presentation.dependsOn(business)
business.dependsOn(data)
data.dependsOnNothing()
}
}
})
}
For Kotest to function correctly the Kotest test name has to be explicitly passed. See theKotest Support page.
The Kotest testing framework project dependency should be added to the project. See starter projects to get a complete sample project.
For more Konsist architectural checks see Protect Kotlin Project Architecture Using Konsist article.

Summary

This is the basic way of using Konsist. Take a look at this guide describing how to debug Konsist tests Debug Konsist Test to get a better understanding of how Konsist works.
Please review the Konsist documentation (this website) to read about more advanced topics and various use cases.