Максим Ковалев

Настройка Kover в многомодульном Android-проекте

💡 Kover - это утилита (и Gradle-плагин) от JetBrains для сбора данных по покрытию тестами (test coverage).

Официальные доки не объясняют прямо как настроить проект, поэтому пришлось разбираться самостоятельно.

Надеюсь этот гайд поможет вам пройти мой путь быстрее.

Буду рад ответить на любые вопросы в:

💡 Гайд актуален для версии 0.7.6. DSL плагина постоянно меняется, поэтому с новой версией что-то обязательно сломается.

TL;DR

Хочется просто посмотреть полный конфиг? Пожалуйста!
plugins {
  id "org.jetbrains.kotlinx.kover" version "0.7.6" apply false
}

subprojects {
  apply plugin: "org.jetbrains.kotlinx.kover"

  kover {
    useJacoco()
  }

  koverReport {
    filters {
      excludes {
        classes(
            // Android
            '**/R.class',
            '**/R$*.class',
            '**/BuildConfig.*',
            '**/Manifest*.*',
            // Several "$" in class name (not supported by JaCoCo)
            '**/*$$*',
            '**/*$Lambda$*.*',
            '**/*$inlined$*.*',
            // Dagger
            '**/*Dagger*.*',
            '**/*MembersInjector*.*',
            '**/*_Provide*Factory*.*',
            '**/*_Factory*.*',
            // Realm
            '**/io/realm/*'
        )
      }
    }
  }
  
  plugins.withType(com.android.build.gradle.api.AndroidBasePlugin) {
    configurations.implementation {
      dependencies.withType(ProjectDependency) {
        project.dependencies.kover dependencyProject
      }
    }

    configurations.api {
      dependencies.withType(ProjectDependency) {
        project.dependencies.kover dependencyProject
      }
    }
  }
}

Почему именно Kover?

Я долго откладывал использование Kover, потому что у авторов очень творческий подход к дизайну плагина - синтаксис настройки меняется с каждой минорной версией. Понимаю, релиз 1.0 ещё не вышел, можно менять что угодно. Правда, в таком состоянии проект находится уже 3 года. Сложно говорить о production-ready с таким отношением (привет ранним версиям Swift!).

Поэтому, пару лет назад, когда надо было настроить покрытие в проекте, я выбрал замечательный https://github.com/NeoTech-Software/Android-Root-Coverage-Plugin. Он максимально прост в настройке и заточен под Android-проекты. К сожалению у автора возникли сложности с поддержкой AGP 8 (на момент написания статьи ещё нет релиза, который поддерживает его). А переход на AGP 8 - это обязательное условие для targetSdk 34. Одно потянулось за другое. Дальше пользоваться rootCoverage было невозможно. Прощай, милый друг.

Kover выделяется среди остальных вариантов тем, что поддерживается JetBrains, а значит можно расчитывать на быстрое решние проблем совместимости с AGP. Сами же данные по покрытию, я надеюсь, будут максимально точными - кто может точнее собирать данные по Kotlin, если не его авторы?

После перехода процент покрытия слегка поменялся, даже с учетом того, что я включил JaCoCo в качестве движка для Kover (rootCoverage тоже работает на JaCoCo). Это не проблема - в покрытии не так важна абсолютная цифра, как динамика.

Пошаговая настройка

Весь код нужно добавлять в корневой build.gradle проекта.

Бонус: связываем Kover с SonarQube/SonarCloud

Для отображения данных от Kover в плагине Sonar нужно настроить свойство sonar.coverage.jacoco.xmlReportPaths.

Это можно сделать так:

sonar {
  properties {
    property 'sonar.coverage.jacoco.xmlReportPaths', "${rootProject.rootDir}/**/build/reports/kover/report*.xml"
  }
}

Теперь любой репорт, который сгенерирует Kover, будет отправлен в Sonar.

Хочешь полный гайд по настройке плагина Sonar? Напиши мне!