Jacoco란?
Java 코드의 커버리지를 체크하는 라이브러리다.
왜 사용하게 되었나?
이전 프로젝트에서 CI의 필요성을 느끼고 도입하기로 결정하였다. 이때 제대로된 CI를 하기 위해서 테스트 코드가 필수적이라고 생각하였고 최소 커버리지를 설정할 수 있는 Jacoco를 사용하게 되었다.
Jacoco 적용
build.gradle 내용을 수정해주도록 하자. (코드들은 이전 프로젝트인 coretime을 기준으로 작성되었다.)
플러그인 추가
우선 Jacoco 플러그인을 추가한다.
plugins { id 'org.springframework.boot' version '2.6.8' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" id 'java' id 'jacoco' } ... jacoco { toolVersion = '0.8.7' }
테스트 후 jacocoTestReport 수행
테스트 시 Jacoco 리포트를 자동으로 작성할 수 있도록 설정한다.
tasks.named('test') { useJUnitPlatform() finalizedBy 'jacocoTestReport' }
finalizedBy
를 이용하여 다음으로 실행할 태스크 명시한다.jacocoTestReport
jacoco 보고서를 저장하는 태스크이다. Jacoco 보고서란 커버리지를 개발자가 쉽게 파악하기 위해 시각화해 주는 것을 의미한다.
jacocoTestReport { reports { html.destination file("${buildDir}/jacocoHtml") xml.enabled false csv.enabled false } def Qdomains = [] for (qPattern in '**/QA'..'**/QZ') { Qdomains.add(qPattern + '*') } afterEvaluate { classDirectories.setFrom( files(classDirectories.files.collect { fileTree(dir: it, excludes: [ "com/prgrms/coretime/common/*", "**/dto/*", "**/domain/*", "**/controller/*", "**/util/*", "**/*Validator", "com/prgrms/coretime/CoretimeApplication.class" ] + Qdomains) }) ) } finalizedBy 'jacocoTestCoverageVerification' }
reports
- 원하는 종류의 보고서(
html
,xml
,csv
)를 키고 끌 수 있다. - 제공된 보고서가 어디에 저장될지 경로를 설정할 수 있다.
(
html.destination file("${buildDir}/jacocoHtml")
)- 보고서에 포함되지 않을 클래스
def Qdomains = [] for (qPattern in '**/QA'..'**/QZ') { Qdomains.add(qPattern + '*') } afterEvaluate { classDirectories.setFrom( files(classDirectories.files.collect { fileTree(dir: it, excludes: [ "com/prgrms/coretime/common/*", "**/dto/*", "**/domain/*", "**/controller/*", "**/util/*", "com/prgrms/coretime/CoretimeApplication.class" ] + Qdomains) }) ) }
Jacoco 보고서에 포함되지 않을 클래스들을 위와 같이 설정할 수 있다. 현재는 Service 디렉토리에 포함된 클래스에 대해서만 보고서에서 확인할 수 있도록 설정하였다.
def Qdomains = [] for (qPattern in '**/QA'..'**/QZ') { Qdomains.add(qPattern + '*') }
위 코드는 보고서에서 제외될 Q 도메인(QueryDsl을 사용함으로서 생성)의 패턴을
Qdomains
라는 배열에 추가하는 코드이다. 이 방법을 사용함으로서 Q 도메인만 제외할 수 있다고 한다.finalizedBy 'jacocoTestCoverageVerification'
jacocoTestReport
라는 태스크가 종료된 이후 jacocoTestCoverageVerification
라는 태스크를 진행하도록 한다.jacocoTestCoverageVerification
설정한 커버리지 기준을 만족하는지 확인해주는 태스크이다. 아무리 테스트를 통과하더라도 설정한 커버리지 기준을 만족하지 못하면 해당 태스크는 실패하게 된다.
jacocoTestCoverageVerification { def Qdomains = [] for (qPattern in '*.QA'..'*.QZ') { Qdomains.add(qPattern + '*') } violationRules { rule { element = 'CLASS' limit { counter = 'LINE' value = 'COVEREDRATIO' minimum = 0.70 } limit { counter = 'BRANCH' value = 'COVEREDRATIO' minimum = 0.70 } excludes = [ "com.prgrms.coretime.common.*", "*.dto.*", "*.controller.*", "*.domain.*", "*.util.*", "*.*Validator", "com.prgrms.coretime.CoretimeApplication" ] + Qdomains } } }
- violationrules
- rule
- element
- limit
- 커버리지를 적용하지 않을 클래스
- Q 도메인 제외
violationRules
로 커버리지 기준들을 설정할 수 있다.커버리지 기준을 설정할 수 있다.
커버리지 체크 기준을 설정할 수 있다. 현재는 클래스 단위로 커버리지를 확인할 수 있도록 설정하였다.
커버러지의 종류와 비율을 설정할 수 있다. 현재는
LINE
, BRANCH
커버리지를 모두 70%로 설정한 상태이다. LINE
커버리지는 테스트 코드를 통해 실행된 실제 코드의 라인 수를 측정하는 방식이고 BRANCH
커버리지는 테스트 코드를 통해 실행된 분기문을 측정하는 방식이다.Jacoco 보고서 설정과 거의 동일한 방식으로 클래스들을 제외할 수 있다.
excludes
에 커버리지에 포함되지 않을 클래스 명을 지정하여 제외하면 된다. 현재는 Service 디렉토리에 포함된 클래스에 대해서만 커버리지를 확인할 수 있도록 설정하였다.def Qdomains = [] for (qPattern in '*.QA'..'*.QZ') { Qdomains.add(qPattern + '*') }
커버리지 확인에서도 Q도메인은 제외 시켜줘야한다.
마무리
위 내용은 Jacoco에 대한 모든 내용을 다루지 않고 사용해본 것들 그리고 앞으로 사용할 것들을 중심으로 정리하였습니다. 혹시 잘못된 내용이 있거나 내용을 추가하고 싶다면 언제든지 수정해주세요!