Konsist
GitHubSlack (kotlinlang)Twitter
  • 🚀GETTING STARTED
    • What is Konsist?
    • Getting Started
      • Add Konsist Dependency
      • Create First Konsist Test - Declaration Check
      • Create Secound Konsist Test - Architectural Check
    • Articles & Videos
  • ✅WRITING TESTS
    • Create The Scope
    • Declaration Filtering
    • Declaration Assertion
    • Architecture Assertion
    • Suppress Konsist Test
  • ✏️VERYFYING CODEBASE
    • Verify Classes
    • Verify Interfaces
    • Verify Functions
    • Verify Properties
    • Verify Generics
    • Verify Source Declarations
  • 📗FEATURES
    • Add Konsist Existing To Project (Baseline)
    • Debug Konsist Test
    • Declaration
    • Declaration Vs Property
    • Compiler Type Inference
    • Package Wildcard
    • Declaration References
    • Indirect Parents
    • Kotest Support
  • 🔍INSPIRATION
    • Starter Projects
    • Snippets
      • General Snippets
      • Android Snippets
      • Spring Snippets
      • Test Snippets
      • JUnit Snippets
      • Kotest Snippets
      • Architecture Snippets
      • Clean Architecture Snippets
      • Kotlin Serialization Snippets
      • Library Snippets
      • Generic Types Snippets
  • 🎓ADVANCED
    • Isolate Konsist Tests
    • Enable Full Command Line Logging
    • Dynamic Konsist Tests
      • Explicit Test Names
    • When Konsist API Is Not Enough
    • Additional JUnit5 Setup
    • Why There Are No Pre-defined Rules?
    • Konsist Snapshots
  • ❓HELP
    • Getting Help
    • Known Issues
      • java.lang.OutOfMemoryError: Java heap space
    • Compatibility
  • ℹ️OTHER
    • Changelog
    • Project Status
    • Contributing
    • Contributors
    • Assets And Logos
    • Open Source Licenses
    • Sponsor Konsist
Powered by GitBook
On this page
  • Declaration Checks
  • ArchitecturalChecks
  • Summary
Edit on GitHub
Export as PDF
  1. GETTING STARTED

What is Konsist?

NextGetting Started

Last updated 5 months ago

Konsist is a structural linter (static code analyzer) designed for language. Verifying codebase with Konsist enables development teams to enforce architectural rules and class structures through automated testing.

Konsist offers comprehensive verification capabilities that enable developers to enforce architectural rules and maintain code consistency, thereby improving the readability and maintainability of the code. It's like , but for Kotlin language. Whether you're working on , , or projects, Konsist has got you covered.

The Konsist API provides developers with the capability to create custom checks through unit tests, customized to align with the project's unique requirements. Additionally, it offers smooth integration with leading testing frameworks, including , , and , further streamlining the development process.

Konsist is approaching its 1.0 release, marking a significant milestone in its development journey. See the Project Status.

Konsist offers two types of checks, namely Declaration Checks and ArchitecturalChecks, to thoroughly evaluate the codebase.

Declaration Checks

The first type involves declaration checks, where custom tests are created to identify common issues and violations at the declaration level (classes, functions, properties, etc.). These cover various aspects such as class naming, package structure, visibility modifiers, presence of annotations, etc. Here are a few ideas of things to check:

  • Every child class extending ViewModel must have ViewModel suffix

  • Classes with the @Repository annotation should reside in ..repository.. package

  • Every class constructor has alphabetically ordered parameters

  • Every constructor parameter has a name derived from the class name

  • Field injection and m prefix is forbidden

  • Every public member in api package must be documented with KDoc

  • and more...

Here is a sample test that verifies if every use case class resides in domain.usecase package:

class UseCaseKonsistTest {
    @Test
    fun `every use case reside in use case package`() {
        Konsist
            .scopeFromProject() // Define the scope containing all Kotlin files present in the project
            .classes() // Get all class declarations
            .withNameEndingWith("UseCase") // Filter classes heaving name ending with 'UseCase'
            .assertTrue { it.resideInPackage("..domain.usecase..") } // Assert that each class resides in 'any domain.usecase any' package
    }
}
class UseCaseKonsistTest : FreeSpec({
    "every use case reside in use case package" {
        Konsist
        .scopeFromProject() // Define the scope containing all Kotlin files present in the project
        .classes() // Get all class declarations
        .withNameEndingWith("UseCase") // Filter classes heaving name ending with 'UseCase'
        .assertTrue (
                testName = this.testCase.name.testName
         ){ 
              it.resideInPackage("..domain.usecase..") 
         } // Assert that each class resides in 'any domain.usecase any' package
    }
})

For more Konsist test samples see the Snippetssection.

ArchitecturalChecks

  • The domain layer is independent

  • The data layer depends on domain layer

  • The presentation layer depends on domain layer

  • etc.

Here is a Konsist test that verifies if Clean Architecture dependency requirements are valid:

class ArchitectureTest {
    @Test
    fun `clean architecture layers have correct dependencies`() {
        Konsist
            .scopeFromProject() // Define the scope containing all Kotlin files present in project
            .assertArchitecture { // Assert architecture
                // Define layers
                val domain = Layer("Domain", "com.myapp.domain..")
                val presentation = Layer("Presentation", "com.myapp.presentation..")
                val data = Layer("Data", "com.myapp.data..")
    
                // Define architecture assertions
                domain.dependsOnNothing()
                presentation.dependsOn(domain)
                data.dependsOn(domain)
            }
    } 
}
class ArchitectureTest : FreeSpec({
    "every use case reside in use case package" {
        Konsist
            .scopeFromProject() // Define the scope containing all Kotlin files present in project
            .assertArchitecture { // Assert architecture
                // Define layers
                val domain = Layer("Domain", "com.myapp.domain..")
                val presentation = Layer("Presentation", "com.myapp.presentation..")
                val data = Layer("Data", "com.myapp.data..")
    
                // Define architecture assertions
                domain.dependsOnNothing()
                presentation.dependsOn(domain)
                data.dependsOn(domain)
            }
    }
})

These types of checks are useful when the architecture layer is defined by the package, rather than a module where dependencies can be enforced by the build system.

Summary

By utilizing Konsist, teams can be confident that their Kotlin codebase remains standardized and aligned with best practices, making code reviews more efficient and code maintenance smoother.

The second type of revolves around architecture boundaries - they are intended to maintain the separation of concerns between layers.

Consider this simple 3 layer of :

🚀
Konsist checks
Clean Architecture
Kotlin
ArchUnit
Android
Spring
Kotlin Multiplatform
JUnit4
JUnit5
Kotest