Jacoco cho gradle kts
Bài đăng này đã không được cập nhật trong 4 năm
Jacoco là một công cụ check test coverage có từ khá lâu rồi, chúng ta thường config jacoco trong một file .gradle và thêm vào build.gradle của module app khi muốn check coverage.
Gần đây việc gradle sử dụng kotlin trong gradle kts giúp chúng ta có thể config dễ dàng hơn với code kotlin thay vì groovy như trước.
Tuy nhiên hiện tại gradle chưa support việc thêm jacoco từ file gradle.kts riêng biệt nên chúng ta sẽ cần thêm code jacoco vào file gradle.kts của module cần check coverage.
Dưới đây là một ví dụ về việc config jacoco cho gradle kts mà các bạn có thể tham khảo
plugins {
...
jacoco
}
jacoco {
toolVersion = "0.8.5"
}
/** There are two ways to see test result:
* FIRST
* To run this test coverage with buildTypes: Debug; Flavor: Dev
* use command: ./gradlew clean testDevDebugUnitTestCoverage
*
* See result at:
* app/build/reports/jacoco/testDevDebugUnitTestCoverage/html/index.html
*
* SECOND:
* - Click Gradle on the right menu of Android Studio IDE
* - At Project name, expand "app", expand "Tasks", expand "coverage"
* - Run any test you want
*/
project.afterEvaluate {
// Grab all build types and product flavors
val buildTypeNames: List<String> = android.buildTypes.map { it.name }
val productFlavorNames: ArrayList<String> = ArrayList(android.productFlavors.map { it.name })
// When no product flavors defined, use empty
if (productFlavorNames.isEmpty()) productFlavorNames.add("")
productFlavorNames.forEach { productFlavorName ->
buildTypeNames.forEach { buildTypeName ->
val sourceName: String
val sourcePath: String
if (productFlavorName.isEmpty()) {
sourcePath = buildTypeName
sourceName = buildTypeName
} else {
sourcePath = "${productFlavorName}/${buildTypeName}"
sourceName = "${productFlavorName}${buildTypeName.capitalize()}"
}
val testTaskName = "test${sourceName.capitalize()}UnitTest"
// Create coverage task of form 'testFlavorTypeCoverage' depending on 'testFlavorTypeUnitTest'
task<JacocoReport>("${testTaskName}Coverage") {
//where store all test to run follow second way above
group = "coverage"
description =
"Generate Jacoco coverage reports on the ${sourceName.capitalize()} build."
val excludeFiles = arrayListOf(
"**/R.class", "**/R$*.class", "**/BuildConfig.*", "**/Manifest*.*",
"**/*Test*.*", "android/**/*.*",
"**/*_MembersInjector.class",
"**/Dagger*Component.class",
"**/Dagger*Component\$Builder.class",
"**/*_*Factory.class",
"**/*ComponentImpl.class",
"**/*SubComponentBuilder.class",
"**/*Creator.class",
"**/*Application*.*",
"**/*Activity*.*",
"**/*Fragment*.*",
"**/*Adapter*.*",
"**/*Dialog*.*",
"**/*Args*.*",
"**/*Companion*.*",
"**/*Kt*.*",
"**/com/example/moviedb/di/**/*.*",
"**/com/example/moviedb/ui/navigation/**/*.*",
"**/com/example/moviedb/ui/widgets/**/*.*"
)
//Explain to Jacoco where are you .class file java and kotlin
classDirectories.setFrom(
fileTree("${project.buildDir}/intermediates/classes/${sourcePath}").exclude(
excludeFiles
),
fileTree("${project.buildDir}/tmp/kotlin-classes/${sourceName}").exclude(
excludeFiles
)
)
val coverageSourceDirs = arrayListOf(
"src/main/java",
"src/$productFlavorName/java",
"src/$buildTypeName/java"
)
additionalSourceDirs.setFrom(files(coverageSourceDirs))
//Explain to Jacoco where is your source code
sourceDirectories.setFrom(files(coverageSourceDirs))
//execute file .exec to generate data report
executionData.setFrom(files("${project.buildDir}/jacoco/${testTaskName}.exec"))
reports {
xml.isEnabled = true
html.isEnabled = true
}
dependsOn(testTaskName)
}
}
}
}
Các bạn có thể tham khảo source code ở đây https://github.com/dangquanuet/The-Movie-DB-Kotlin/blob/develop/app/build.gradle.kts#L29
Sau đó các bạn có thể tiến hành chạy test coverage như bình thường với jacoco trước đây là qua command line hay là gradle task.
Bài lần này đến đây là kết thúc, hẹn gặp lại các bạn sau
All rights reserved