
최근에 진행한 프로젝트에 Jacoco를 적용해서 우리 프로젝트의 Code Coverage 정도를 측정해보았다.
IntelliJ 에서도 간편하게 코드 커버리지를 확인해 보았고, github actions를 통해 PR을 생성하면 해당 PR에서 작성한 코드와 전체 코드 커버리지를 알려주는 라이브러리를 도입했다.
코드 커버리지는 코드의 실행 여부를 기반으로 코드의 완성도를 측정하는 방법이다. 하지만 코드 커버리지가 높다는 것만으로 코드 품질 또한 높다고 단언할 수는 없다. 코드 커버리지는 코드의 어느 부분이 테스트에 의해 실행되었는지를 나타내는 지표일 뿐, 테스트의 질이나 코드의 안정성을 직접적으로 측정하지는 않기 때문이다.
JaCoCo(Java Code Coverage Library)는 Java 코드에 대한 코드 커버리지를 측정하는 라이브러리다.
커버리지 데이터는 개발자가 코드의 테스트가 충분한지, 어떤 부분의 테스트가 부족했는지 등을 이해하는 데 도움을 줄 수 있다.
plugins {
id 'jacoco'
}
test {
useJUnitPlatform()
finalizedBy jacocoTestReport
}
jacoco {
toolVersion = "0.8.8"
reportsDir = file("$buildDir/jacoco")
}
jacocoTestReport {
dependsOn test
reports {
xml.enabled true
html.enabled true
}
def Qdomains = []
for (qPattern in '**/QA'..'**/QZ') {
Qdomains.add(qPattern + '*')
}
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: [
'**/jwt/**',
'**/init/**',
'**/exception/**',
'**/auth/**'
] + Qdomains)
}))
}
}
plugins { id 'jacoco' }jacoco 플러그인 추가
test { useJUnitPlatform() finalizedBy jacocoTestReport }JUnit Platform(JUnit5)을 사용하여 테스트를 실행하고, 테스트 완료 후 'jacocoTestReport'를 자동 생성한다.
jacoco { toolVersion = "0.8.8" reportsDir = file("$buildDir/jacoco") }사용할 JaCoCo 버전과 커버리지 리포트가 저장될 디렉토리를 정의한다.
jacocoTestReport { dependsOn test reports { xml.enabled true html.enabled true csv.enabled false }JacocoReport를 생성한다. 세가지 형식 중 원하는 형식으로 리포트 저장이 가능하며, CI 구축을 위해서는 xml, html이 필요하다.
def Qdomains = [] for (qPattern in '**/QA'..'**/QZ') { Qdomains.add(qPattern + '*') }Q 클래스 전부를 테스트 평가에서 제외시킬 것이다.
afterEvaluate { classDirectories.setFrom(files(classDirectories.files.collect { // 디렉토리 별로 파일 트리를 생성하고, 제외할 패턴을 지정 fileTree(dir: it, exclude: [ '**/jwt/**', '**/init/**', '**/exception/**', '**/auth/**' ] + Qdomains) })) } }커버리지 측정 대상 클래스를 설정한다. 디렉토리 별로 파일 트리를 생성하여 평가하고, 평가에서 제외할 클래스를 지정했다.
이후 JacocoCoverageVerification을 통해 커버리지 퍼센티지를 설정하여 build를 실패하거나 성공 시킬 수 있고, 커버리지 측정의 기준이 되는 요소를 설정할 수 있는데, 해당 부분은 팀원들과 상의 후에 정해야 하기도 하고, 프로젝트 막바지에 jacoco를 적용했기 때문에 이 프로젝트에서는 제외하고 알아본 것으로만 만족했다. 다음 프로젝트에서 적용하면 좋을 듯 하다.
그리고 측정에서 제외할 클래스를 지정할 수 있는데, jacocoTestReport와 jacocoTestCoverageVerification의 클래스를 포함, 제외 시키는 방식이 달라 삽질도 여러번 하느라 시간을 많이 투자했다. 제외를 하지 않아도 결과는 잘 나오지만 아래 사진처럼 토탈 코드 커버리지가 9%로 보여지도록 둘 수 없었다. 어쩐지 억울한 기분이라..


build/jacoco/test/html/index.html파일에서 커버리지를 한눈에 볼 수 있다.
현재 토탈 코드 커버리지는 84%로 측정되었다.


파일로 접근하면 해당 코드의 라인 커버리지를 확인할 수 있다.
초록색은 테스트에서 실행된 라인을, 빨간색은 실행되지 않은 라인을 의미한다.
조건문은 true, false 케이스가 둘 다 테스트 되었다면 초록색, 둘 중 하나만 테스트 되었다면 노란색으로 나타난다.

Code Coverage For Java Plugin을 추가한다.

Run ... with Coverage를 실행시킨다.

클래스, 메서드, 라인 별 코드 커버리지 퍼센트를 확인할 수 있다.
- name: Test Coverage Report
id: jacoco
uses: madrapps/jacoco-report@v1.6.1
with:
title: Test Coverage Report
paths: ${{ github.workspace }}/build/jacoco/test/jacocoTestReport.xml
token: ${{ secrets.GITHUB_TOKEN }}
min-coverage-changed-files: 60
min-coverage-overall: 60
debug-mode: true
Jacoco 코드 커버리지 보고서를 생성하고 PR에 결과를 코멘트로 제공한다.
paths: ${{ github.workspace }}/build/jacoco/test/jacocoTestReport.xml token: ${{ secrets.GITHUB_TOKEN }}github.workspace와 secrets.GITHUB_TOKEN은 Github action 기본 설정값이므로 변경하지 않고, jacocoTestReport.xml 파일 경로만 정의한다.
min-coverage-changed-files: 60 min-coverage-overall: 60커밋된 파일, 전체 파일에 대한 최소 커버리지 요구사항을 둘 다 60%로 설정했다.

행복 별거없다.
참고
Gradle 프로젝트에 JaCoCo 설정하기
[Spring] JaCoCo를 활용한 테스트 커버리지 확인
좌충우돌 jacoco 적용기
Jacoco with Github Action