Jacoco
- 자바코드의 커버리지를 체크할 때 사용하는 오픈소스 라이브러리이다.
- CI/CD와 연계해 테스트 커버리지를 충분히 채우지 못하면 배포가 되지 못하게 하는 등 구성원들에게 테스트 코드를 강제할 때 사용할 수 있다.
- 여기서 커버리지란 Test를 실행했을 때 Code가 얼마나 빈틈없이 실행됐는지 측정한 수치이다.
Gradle 설정
- Java 17 / Spring Boot 3.1.2 / Gradle 8.2.1 기준
build.gradle (groovy)
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.2'
id 'io.spring.dependency-management' version '1.1.2'
// 1. Jacoco 플러그인 추가
id 'jacoco'
}
group = 'com.onebyte'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
/**
* Test Implementation
*/
testImplementation 'org.springframework.boot:spring-boot-starter-test'
...
}
/**
* Jacoco
*/
tasks.named('test') {
useJUnitPlatform()
// 2. test 종료 후 jacocoTestReport 실행
finalizedBy jacocoTestReport
}
// 3. 커버리지 결과를 html 파일로 가공
jacocoTestReport {
dependsOn test
}
// 4. 커버리지 기준을 만족하는지 확인해 주는 task
jacocoTestCoverageVerification {
violationRules {
rule {
enabled = true
element = 'CLASS'
limit {
counter = 'BRANCH'
value = 'COVERDRATIO'
minimum = 0.80
}
excludes = listOf(
"*.Config.*",
)
}
}
}
build.gradle.kts
plugins {
java
id("org.springframework.boot") version "3.1.2"
id("io.spring.dependency-management") version "1.1.2"
// 1. Jacoco 플러그인 추가
id("jacoco")
}
group = "com.onebyte"
version = "0.0.1-SNAPSHOT"
java {
sourceCompatibility = JavaVersion.VERSION_17
}
configurations {
compileOnly {
extendsFrom(configurations.annotationProcessor.get())
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-web")
compileOnly("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok")
runtimeOnly("com.mysql:mysql-connector-j")
/**
* Test
*/
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
/**
* Jacoco
*/
tasks {
test {
useJUnitPlatform()
// 2. test 종료 후 jacocoTestReport 실행
finalizedBy(jacocoTestReport)
}
// 3. 커버리지 결과를 html 파일로 가공
jacocoTestReport {
dependsOn(test)
}
// 4. 커버리지 기준을 만족하는지 확인해주는 task
jacocoTestCoverageVerification {
violationRules {
rule {
enabled = true
element = "CLASS"
limit {
counter = "BRANCH"
value = "COVEREDRATIO"
minimum = "0.80".toBigDecimal()
}
// 커버리지 체크 제외 클래스 지정
excludes = listOf(
"*.Config.*",
)
}
}
}
}
설명
- test task에서 finalizedBy jacocoTestReport를 이용해 테스트가 종료된 후 jacocoTestReport가 실행되도록 설정했다.
- jacocoTestReport는 커버리지 결과는 xml, csv, html과 같이 보기 쉬운 파일로 생성해주는 task이다.
- jacocoTestCoverageCerification는 커버리지 기준, 커버리지 대상 등에 대한 기준을 정할 수 있는 task이다. 자세한 설정에 대한 내용은 아래와 같다.
tasks {
...
jacocoTestCoverageVerification {
violationRules {
rule {
// 커버리지를 아래 옵션으로 키고 끌 수 있다.
enabled = true
// 룰을 체크할 단위는 클래스 단위로 설정한 것
element = "CLASS"
limit {
counter = "BRANCH" // 브랜치 대상
value = "COVEREDRATIO" // 커버리지 비율
minimum = "0.80".toBigDecimal() // 최소 80퍼센트
}
// 커버리지 체크 제외 클래스 지정
excludes = listOf(
"*.Config.*",
)
}
}
}
}
gradle test 실행
- 위와 같이 jacoco를 설정하고 test를 실행해보자.
- build/reports/jacoco/test/html 디렉토리에 index.html 파일이 생성되었다.
- index.html을 열면 아래와 같이 커버리지 페이지를 확인할 수 있다.
- 어떤 부분이 테스트되었고 테스트되지 않았는지 확인할 수 있다.
참고자료
- 우형 블로그: https://techblog.woowahan.com/2661/
- Jacoco 버전: https://www.eclemma.org/jacoco/
- Gradle JacocoPluginExtension: https://docs.gradle.org/current/dsl/org.gradle.testing.jacoco.plugins.JacocoPluginExtension.html
- build.gradle.kts: https://github.com/th-deng/jacoco-on-gradle-sample/blob/master/build.gradle.kts