Skip to content

Latest commit

 

History

History
472 lines (384 loc) · 14.3 KB

README.md

File metadata and controls

472 lines (384 loc) · 14.3 KB

Kotlinx-Kover

JetBrains incubator project GitHub license

Kover - Gradle plugin for Kotlin code coverage agents: IntelliJ and JaCoCo.

Minimal supported Gradle version: 6.4.

Table of content

Features

  • Collecting the code coverage for JVM test tasks
  • XML and HTML reports generation
  • Support of Kotlin/JVM, Kotlin Multiplatform and mixed Kotlin-Java sources with zero additional configuration
  • Kotlin Android support without dividing them into build types and flavours
  • Customizable filters for instrumented classes

Quickstart

Apply plugin to a single-module build

Applying plugins with the plugins DSL

In top level build file

Kotlin
plugins {
     id("org.jetbrains.kotlinx.kover") version "0.4.4"
}
Groovy
plugins {
    id 'org.jetbrains.kotlinx.kover' version '0.4.4'
}

Legacy Plugin Application: applying plugins with the buildscript block

In top level build file

Kotlin
buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath("org.jetbrains.kotlinx:kover:0.4.4")
    }
}

apply(plugin = "kover")
Groovy
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.jetbrains.kotlinx:kover:0.4.4'
    }
}
  
apply plugin: 'kover'    

Apply plugin to a multi-module build

To apply the plugin to all Gradle modules, you just need to apply the plugin only to the root module, as shown above. Applying the plugin to submodules if you have already applied it to the root module will cause configuration error.

Configuration

Once applied, the plugin can be used out of the box without additional configuration.

However, in some cases, custom settings are needed - this can be done by configuring special extensions and tasks.

Configuring JVM test task

If you need to disable or filter instrumentation for a some test task, you may configure the Kover extension for it.

For example, to configure a standard test task for Kotlin/JVM named test, you need to add the following code to the build script of the module where this task is declared

Kotlin
tasks.test {
    extensions.configure(kotlinx.kover.api.KoverTaskExtension::class) {
        isDisabled = false
        binaryReportFile.set(file("$buildDir/custom/result.bin"))
        includes = listOf("com.example.*")
        excludes = listOf("com.example.subpackage.*")
    }
}
Groovy
tasks.test {
    kover {
        disabled = false
        binaryReportFile.set(file("$buildDir/custom/result.bin"))
        includes = ['com.example.*']
        excludes = ['com.example.subpackage.*']
    }
}

For other platforms (Android, Kotlin-Multiplatform) the name may differ, you may also have several test tasks, so you first need to determine the name of the required task.

Example of configuring test task for build type debug in Android:

Kotlin
android {
    // other Android declarations

    testOptions {
        unitTests.all {
            if (it.name == "testDebugUnitTest") {
                extensions.configure(kotlinx.kover.api.KoverTaskExtension::class) {
                    isDisabled = false
                    binaryReportFile.set(file("$buildDir/custom/debug-report.bin"))
                    includes = listOf("com.example.*")
                    excludes = listOf("com.example.subpackage.*")
                }
            }
        }
    }
}
Groovy
android {
    // other Android declarations

    testOptions {
        unitTests.all {
            if (name == "testDebugUnitTest") {
                kover {
                    disabled = false
                    binaryReportFile.set(file("$buildDir/custom/debug-report.bin"))
                    includes = ['com.example.*']
                    excludes = ['com.example.subpackage.*']
                }
            }
        }
    }
}

Configuring aggregated reports

Aggregated report provides report using combined classpath and coverage stats from the module in which plugin is applied and all its submodules.

If you need to change the name of the XML report file or HTML directory, you may configure the corresponding tasks in the module in which the plugin is applied (usually this is the root module).

Kotlin
tasks.koverHtmlReport {
    isEnabled = true                        // false to disable report generation
    htmlReportDir.set(layout.buildDirectory.dir("my-agg-report/html-result"))
}

tasks.koverXmlReport {
    isEnabled = true                        // false to disable report generation
    xmlReportFile.set(layout.buildDirectory.file("my-agg-report/result.xml"))
}
Groovy
tasks.koverHtmlReport {
    enabled = true                          // false to disable report generation
    htmlReportDir.set(layout.buildDirectory.dir("my-reports/html-result"))
}

tasks.koverXmlReport {
    enabled = true                          // false to disable report generation
    xmlReportFile.set(layout.buildDirectory.file("my-reports/result.xml"))
}

Configuring module reports

If you need to change the name of the XML report file or HTML directory for a specific module, you may configure the corresponding tasks in this module.

Kotlin
tasks.koverHtmlModuleReport {
    isEnabled = true                        // false to disable report generation
    htmlReportDir.set(layout.buildDirectory.dir("my-module-report/html-result"))
}

tasks.koverXmlModuleReport {
    isEnabled = true                        // false to disable report generation
    xmlReportFile.set(layout.buildDirectory.file("my-module-report/result.xml"))
}
Groovy
tasks.koverHtmlModuleReport {
    enabled = true                          // false to disable report generation
    htmlReportDir.set(layout.buildDirectory.dir("my-module-report/html-result"))
}

tasks.koverXmlModuleReport {
    enabled = true                          // false to disable report generation
    xmlReportFile.set(layout.buildDirectory.file("my-module-report/result.xml"))
}

You may collect all modules reports into one directory using koverCollectModuleReports task. Also, you may specify custom directory to collect modules reports in the build file of the module in which the plugin is applied (usually this is the root module):

Kotlin
tasks.koverCollectModuleReports {
  outputDir.set(layout.buildDirectory.dir("all-modules-reports") )
}
Groovy
tasks.koverCollectModuleReports {
  outputDir.set(layout.buildDirectory.dir("all-modules-reports") )
}

Configuring entire plugin

In the module in which the plugin is applied, you need to add code:

Kotlin
kover {
    isDisabled = false                      // true to disable instrumentation of all test tasks in all modules
    coverageEngine.set(kotlinx.kover.api.CoverageEngine.INTELLIJ) // change instrumentation agent and reporter
    intellijEngineVersion.set("1.0.640")    // change version of IntelliJ agent and reporter
    jacocoEngineVersion.set("0.8.7")        // change version of JaCoCo agent and reporter
    generateReportOnCheck.set(true)         // false to do not execute `koverReport` task before `check` task
    disabledModules = setOf()               // setOf("module-name") to disable coverage for module with name `module-name`
    instrumentAndroidPackage = false        // true to instrument packages `android.*` and `com.android.*`
}
Groovy
kover {
    disabled = false                        // true to disable instrumentation of all test tasks in all modules
    coverageEngine.set(kotlinx.kover.api.CoverageEngine.INTELLIJ) // change instrumentation agent and reporter
    intellijEngineVersion.set('1.0.640')    // change version of IntelliJ agent and reporter
    jacocoEngineVersion.set('0.8.7')        // change version of JaCoCo agent and reporter
    generateReportOnCheck.set(true)         // false to do not execute `koverReport` task before `check` task
    disabledModules = []                    // ["module-name"] to disable coverage for module with name `module-name`
    instrumentAndroidPackage = false        // true to instrument packages `android.*` and `com.android.*`
}

Verification

You may specify one or more rules that check the values of the code coverage counters.

Validation rules work for both types of agents.

The plugin currently only supports line counter values.

To add a rule check to cover the code of all modules, you need to add configuration to the module in which the plugin is applied (usually this is the root module):

Kotlin
tasks.koverVerify {
    rule {
        name = "Minimum number of lines covered"
        bound {
            minValue = 100000
            valueType = kotlinx.kover.api.VerificationValueType.COVERED_LINES_COUNT
        }
    }
    rule {
        // rule without a custom name
        bound {
            minValue = 1
            maxValue = 1000
            valueType = kotlinx.kover.api.VerificationValueType.MISSED_LINES_COUNT
        }
    }
    rule {
        name = "Minimal line coverage rate in percent"
        bound {
            minValue = 50
            // valueType is kotlinx.kover.api.VerificationValueType.COVERED_LINES_PERCENTAGE by default
       }
    }
}
Groovy
tasks.koverVerify {
    rule {
        name = "Minimum number of lines covered"
        bound {
            minValue = 100000
            valueType = 'COVERED_LINES_COUNT'
        }
    }
    rule {
        // rule without a custom name
        bound {
            minValue = 1
            maxValue = 1000
            valueType = 'MISSED_LINES_COUNT'
        }
    }
    rule {
        name = "Minimal line coverage rate in percent"
        bound {
            minValue = 50
            // valueType is 'COVERED_LINES_PERCENTAGE' by default
        }
    }
}

To add rules for code coverage checks for one specific module, you need to add a configuration to this module:

Kotlin
tasks.koverModuleVerify {
    rule {
        name = "Minimal line coverage rate in percent"
        bound {
            minValue = 75
       }
    }
}
Groovy
tasks.koverModuleVerify {
    rule {
        name = "Minimal line coverage rate in percent"
        bound {
            minValue = 75
        }
    }
}

Tasks

The plugin, when applied, automatically creates tasks for the module in which it is applied (usually this is the root module):

  • koverHtmlReport - Generates code coverage HTML report for all enabled test tasks in all modules.
  • koverXmlReport - Generates code coverage XML report for all enabled test tasks in all modules.
  • koverReport - Executes both koverXmlReport and koverHtmlReport tasks. Executes before check task if property generateReportOnCheck for KoverExtension is true (see).
  • koverVerify - Verifies code coverage metrics of all modules based on specified rules. Always executes before check task.
  • koverCollectModuleReports - Collects all modules reports into one directory. Default directory is $buildDir/reports/kover/modules, names for XML reports and dirs for HTML are modules names. Executing this task does not run koverXmlReport or koverHtmlReport, it only copies previously created reports if they exist to the output directory.

Tasks that are created for all modules:

  • koverHtmlModuleReport - Generates code coverage HTML report for all enabled test tasks in one module.
  • koverXmlModuleReport - Generates code coverage XML report for all enabled test tasks in one module.
  • koverModuleReport - Executes both koverXmlModuleReport and koverHtmlModuleReport tasks.
  • koverModuleVerify - Verifies code coverage metrics of one module based on specified rules. Always executes before check task.

Implicit plugin dependencies

During the applying of the plugin, the artifacts of the JaCoCo or IntelliJ toolkit are dynamically loaded. They are downloaded from the mavenCentral repository.

For the plugin to work correctly, you need to make sure that the mavenCentral or its mirror is added to the list by the repository of the module in which the plugin is applied (usually this is the root module) and add it if necessary.

Kotlin
repositories {
    mavenCentral()
}
Groovy
repositories {
  mavenCentral()
}