Java code coverage. 자바 코드 커버리지를 체크하는 데에 사용되는 오픈소스 라이브러리
buildTypes{
release{ ... }
debug{ ... }
}
flavorDimensions "flavors"
productFlavors{
open{ ... }
dev{ ... }
}
jacoco_version = '0.8.6'
dependencies{
...
classpath "org.jacoco:org.jacoco.core:$jacoco_version"
}
allprojects{
apply plugin: 'jacoco'
...
}
dependencies{
apply from: "$project.rootDir/jacoco.gradle"
...
}
productFlavors.each{productFlavorName->
buildTypes.each{buildTypeName->
def sourceName, sourcePath
if (!productFlavorName) {
sourceName = sourcePath = "${buildTypeName}"
} else {
sourceName = "${productFlavorName}${buildTypeName.capitalize()}"
sourcePath = "${productFlavorName}/${buildTypeName}"
}
def testTaskName = "test${sourceName.capitalize()}UnitTest"
// 필터링할 파일들 설정
def fileFilter = [
// data binding
'**/*Binding*.*',
'**/BR.*',
// android
'**/R.class',
'**/R$*.class',
...
// kotlin
'**/*MapperImpl*.*',
'**/*$ViewInjector*.*',
...
// sealed and data classes
'**/*$Result$*.*',
'**/*Dto*.*',
...
// adapters generated by moshi
'**/*JsonAdapter.*',
...
]
// 소스 디렉토리
def coverageSourceDirs = ["src/main/java",
"src/$productFlavorName/java",
"src/$buildTypeName/java"]
// 소스 디렉토리 내 클래스를 컴파일한 결과인 *.class 파일이 있는 디렉토리 지정
def javaTree = fileTree(dir: "${project.buildDir}/intermediates/javac/$sourceName/classes", excludes: fileFilter)
def kotlinTree = fileTree(dir: "${project.buildDir}/tmp/kotlin-classes/$sourceName", excludes: fileFilter)
// Create coverage task of form 'testFlavorTypeCoverage' depending on 'testFlavorTypeUnitTest'
// dependsOn : 테스트 수행 후 커버리지 측정이 진행될 수 있도록, 유닛 테스트를 수행하는 태스크 이름으로 지정
// 사용하는 안드로이드 그래들 빌드 플러그인 버전에 따라 다르게 지정해야 하며, 사용 중인 플러그인 버전은 루트 프로젝트의 build.gradle에서 확인 가능
// 버전별로 지정해야 하는 이름은 다음과 같음
// 1.2.3 이하: testDebug
// 1.3.0 이상: testDebugUnitTest
task "${testTaskName}Coverage"(type: JacocoReport, dependsOn: "$testTaskName"){
group = "Reporting"
description = "Generate Jacoco coverage reports on the ${sourceName.capitalize()} build."
// sourceDirectories : 커버리지를 측정할 소스 디렉토리를 지정
sourceDirectories.setFrom(files(coverageSourceDirs))
additionalSourceDirs.setFrom(files(coverageSourceDirs))
// classDirectories : 소스 디렉토리 내 클래스를 컴파일한 결과인 *.class 파일이 있는 디렉토리를 지정
// 커버리지 측정에서 제외해야 하는 클래스(R, 안드로이드 서포트 라이브러리 등)는 제외
classDirectories.from = files([javaTree], [kotlinTree])
// executionData: 커버리지 측정 결과를 저장할 파일 이름을 지정. 플러그인 버전에 따라 다르게 지정
// 1.2.3 이하: testDebug.exec
// 1.3.0 이상: testDebugUnitTest.exec
executionData.from = files("${project.buildDir}/jacoco/${testTaskName}.exec")
// reports : 커버리지 결과 리포트 형식을 지정
reports {
csv.enabled false // change if needed
xml.enabled false // change if needed
html {
enabled true
destination file("${buildDir}/coverage-report")
}
}
}
}
}
task "${testTaskName}CoverageVerification"(type: JacocoCoverageVerification, dependsOn: "${testTaskName}Coverage") {
group = "Reporting"
description = "Generate Jacoco coverage reports and verification and on the ${sourceName.capitalize()} build."
// sourceDirectories : 커버리지를 측정할 소스 디렉토리를 지정
...
// classDirectories : 소스 디렉토리 내 클래스를 컴파일한 결과인 *.class 파일이 있는 디렉토리를 지정
...
// executionData: 커버리지 측정 결과를 저장할 파일 이름을 지정. 플러그인 버전에 따라 다르게 지정
...
violationRules {
// 여러 룰 생성 가능
rule {
// 룰 on/off
enabled = true
// 룰 체크할 단위는 클래스 단위
element = 'CLASS'
// 라인 커버리지를 최소한 80% 만족시켜야 함
limit {
counter = 'LINE'
value = 'COVEREDRATIO'
minimum = 0.80
}
// 빈 줄을 제외한 코드의 라인수를 최대 200라인으로 제한
limit {
counter = 'LINE'
value = 'TOTALCOUNT'
maximum = 200
}
// 커버리지 체크 제외할 클래스들
excludes = [
//'*.test.*',
]
}
}
}
커버리지 기준 만족했을 때
커버리지 기준 만족하지 못했을 때
커버리지를 체크할 기준(단위)을 정할 수 있음
Default 값은 BUNDLE
limit 메서드를 통해 지정할 수 있으며 커버리지 측정의 최소 단위
Default 값은 INSTRUCTION
limit 메서드를 통해 지정할 수 있으며 측정한 커버리지를 어떠한 방식으로 보여줄 것인지를 말함
Default 값은 COVEREDRATIO