1. Introduction

In the evolving landscape of software development, code coverage tools are indispensable for ensuring the quality and reliability of code. Kotlin is gaining popularity because it boasts concise syntax and interoperability with Java. Tools that assist with quality are important factors for the ecosystem.

Kotlinx-Kover is a code coverage tool that provides a Gradle plugin and is a valuable tool for Kotlin developers. This tutorial delves into Kotlinx-Kover, exploring its features, setup, and integration, aimed at enhancing our Kotlin projects.

2. Key Features of Kotlinx-Kover

Kotlinx-Kover is a Gradle plugin designed for native Kotlin code coverage. It’s noteworthy for its compatibility with both Kotlin JVM and Kotlin Multiplatform projects, as well as its support for mixed Kotlin and Java sources. Utilizing the JaCoCo library allows for seamless coverage measurement and report generation handling in familiar formats like HTML and XML. Let’s take a look at some key aspects of Kover:

  • A code coverage report of all the JVM tests, however, JS and native targets are not currently supported
  • Comprehensive HTML and XML reports
  • Verification rules with boundaries to track coverage effectively
  • Automatically configured Kover gradle tasks that work with existing compilation and test tasks
  • Kotlin Android projects with build variants support, although instrumentation tests on Android devices are not yet supported

3. Installation and Configuration

The simplicity of adding the Kover plugin to our build.gradle.kts file is a highlight, streamlining the integration process into our existing workflow. Once installed, running gradle koverReport generates coverage files in XML and HTML formats. Afterward, they can be found in the ./build/reports/kover directory of our project.

The html/index.html file provides a human-readable report, making it easier to analyze coverage data. Let’s simply add it to our plugins declaration:

plugins {
     id("org.jetbrains.kotlinx.kover") version "0.7.5"
}

Kover comes with default configurations. Let’s see how to configure some of the simpler behaviors in build.gradle.kts:

koverReport {
    filters {
        excludes {
            classes("com.baeldung.code.not.covered")
        }
    }

    verify {
        rule {
            isEnabled = true
            bound {
                minValue = 80 // Minimum coverage percentage
            }
        }
    }
}

This configuration sets up Kover with basic filters and a verification rule. The minValue in the verification rule specifies the minimum code coverage percentage required.

4. Advanced Configuration of Kotlinx-Kover

Kotlinx-Kover offers advanced configuration options to cater to complex project requirements. In this section, we’ll dive deeper into the advanced features, focusing on filters and verification rules, which are essential for fine-tuning code coverage analysis.

4.1. Filtering Options

Filters in Kotlinx-Kover allow us to tailor coverage reports by including or excluding specific classes, packages, or annotations. For example, we can exclude classes like com.baeldung.code.not.covered.NotCoveredClass or entire packages using com.baeldung.code.not.covered.*. We can also exclude specific classes or functions by annotating them with com.baeldung.annotations.ExcludeFromCoverage.

To configure these advanced filters, we must change our Kover configuration:

koverReport {
    filters {
        excludes {
            classes("com.baeldung.code.not.covered.NotCoveredClass") // Exclude specific classes
            packages("com.baeldung.code.not.covered.*") // Exclude a whole package
            annotatedBy("com.baeldung.annotations.ExcludeFromCoverage") // Exclude classes or functions with a specific annotation
        }
        includes {
            classes("com.baeldung.code.covered.CoveredClass") // Include specific classes
        }
    }
  }
}

4.2. Verification Rules

Verification rules in Kotlinx-Kover enable setting specific coverage targets based on different metrics like line and branch coverage. For instance, we might require a minimum of 80% line coverage (MetricType.LINE) and 70% branch coverage (MetricType.BRANCH). Utilizing these rules specifically helps enforce quality standards tailored to our project’s needs:


koverReport {    
    verify {
        rule("Basic Line Coverage") {
            isEnabled = true
            bound {
                minValue = 80 // Minimum coverage percentage
                maxValue = 100 // Maximum coverage percentage (optional)
                metric = MetricType.LINE
                aggregation = AggregationType.COVERED_PERCENTAGE
            }
        }

        rule("Branch Coverage") {
            isEnabled = true
            bound {
                minValue = 70 // Minimum coverage percentage for branches
                metric = MetricType.BRANCH
            }
        }
}

5. Usage in CI/CD Pipelines

Kotlinx-Kover works with CI/CD workflows as well. The coverage report can be subsequently uploaded to platforms like CodeCov or SonarQube, offering insights into coverage trends and evolution over time. Let’s write a GitHub action build to run our Kover plugin:

name: Kotlin Code Coverage

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2

    - name: Set up JDK 11
      uses: actions/setup-java@v2
      with:
        java-version: '11'
        distribution: 'adopt'

    - name: Grant execute permission for gradlew
      run: chmod +x gradlew

    - name: Build with Gradle
      run: ./gradlew build

    - name: Run Kover
      run: ./gradlew koverReport

    - name: Upload Coverage to CodeCov
      uses: codecov/codecov-action@v2
      with:
        files: ./build/reports/kover/xmlReport.xml
        fail_ci_if_error: true

This workflow includes steps to set up the Java environment, check out the code, and build the project using Gradle. Then we run Kotlinx-Kover to generate the coverage report and upload the coverage report to CodeCov.

6. Kover Output Report

Finally, Kover provides many tasks to generate reports in different formats. This includes console logging with the koverLog task and generating binary, non-human-readable reports with koverBinaryReport. There’s also an HTML report that can be generated by calling koverHtmlReport.

Let’s look at a sample HTML report:

coverage report summary

From this summary, we can see that the report usually provides class, method, branch, line, and instruction coverage. In our case, we can see that add() and multiply() are fully covered and highlighted green. max() is only partially covered, so it’s highlighted yellow. Finally, the min() function is highlighted in red because it is completely uncovered.

7. Conclusion

Kotlinx-Kover stands out as a versatile and efficient code coverage tool for Kotlin projects. Its ease of integration, comprehensive reporting capabilities, and advanced configuration options make it a valuable addition to any Kotlin developer’s toolkit. By integrating Kotlinx-Kover into our projects and CI/CD pipelines, we ensure more reliable and high-quality code coverage, ultimately leading to more robust and efficient applications.

As always, the code used in this article is available over on GitHub.