photocard backend server 개발일기
SonarQube , JaCoCo 테스트 커버리지 측정하기
한둥둥
2025. 2. 6. 14:41
SonarQube 관련 글을 읽고 오시면 조금 더 이해하기 좋습니다.
https://seounggyun.tistory.com/302
정적 코드 분석 AWS EC2 SonarQube 사용하여 Github Action CI 하기
🤗 정적 코드 분석 vs 동적 코드 분석정적 코드 분석은 코드가 실행 되기 전 소스 코드 또는 바이너리 코드를 분석해 코드를 직접 실행하지 않고 코드의 구조, 문법, 스타일, 잠재적인 버그, 코
seounggyun.tistory.com
해당 글은 JaCoCo 테스트 커버리지에 대한 내용이기에 SonarQube는 제외하고 글을 작성하겠습니다.
해당 글을 작성한 계기는 SonarQube에서 단위 테스트 코드를 작성했음에도 불구하고, 테스트 커버리지를 인식하지 못하여 찾아보던 중, JaCoCo 와 연동해주어야 테스트 커버리지가 정상적으로 보이는 것을 알게되어 작성합니다.
JaCoCo란?
JaCoCo(Java Code Coverage)는 Java 애플리케이션 코드 커버리지를 측정하는 도구다.
단위 테스트 실행 시 얼마나 많은 코드가 실행되었는지를 분석하여 테스트의 효과성을 평가
JaCoCo 플러그인 설정
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.3'
id 'io.spring.dependency-management' version '1.1.3'
id "org.sonarqube" version "5.0.0.4638"
id "jacoco"
}
// SonarQube 설정
sonar {
properties {
property "sonar.projectKey", "capo-project_capo-backend_9c8ca8d4-60b4-4f51-b018-261f74c69a56"
property "sonar.projectName", "capo-backend"
property "sonar.language", "java"
property "sonar.sourceEncoding", "UTF-8"
property "sonar.sources", "src/main"
property "sonar.tests", "src/test"
property "sonar.java.binaries", "${buildDir}/classes"
property "sonar.test.inclusions", "**/*Test.java"
property 'sonar.coverage.jacoco.xmlReportPaths', "${buildDir}/reports/jacoco/test/jacocoTestReport.xml"
}
}
tasks.named('test') {
useJUnitPlatform()
finalizedBy 'jacocoTestReport'
}
// jacoco 정보
jacoco {
toolVersion = "0.8.11"
layout.buildDirectory.dir("reports/jacoco")
}
// jacoco Report 생성
jacocoTestReport {
dependsOn test // test 종속성 추가
reports {
xml.required = true
csv.required = false
html.required = true
}
def QDomainList = []
for (qPattern in '**/QA'..'**/QZ') { // QClass 대응
QDomainList.add(qPattern + '*')
}
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: [
'**/dto/**',
'**/event/**',
'**/*InitData*',
'**/*Application*',
'**/exception/**',
'**/service/alarm/**',
'**/aop/**',
'**/config/**',
'**/MemberRole*'
] + QDomainList)
}))
}
// finalizedBy 'jacocoTestCoverageVerification' // jacocoTestReport 태스크가 끝난 후 실행
}
// jacoco Test 유효성 확인
jacocoTestCoverageVerification {
def QDomainList = []
for (qPattern in '*.QA'..'*.QZ') { // QClass 대응
QDomainList.add(qPattern + '*')
}
violationRules {
rule {
enabled = true // 규칙 활성화 여부
element = 'CLASS' // 커버리지를 체크할 단위 설정
// 코드 커버리지를 측정할 때 사용되는 지표
limit {
counter = 'LINE'
value = 'COVEREDRATIO'
minimum = 0.30
}
limit {
counter = 'BRANCH'
value = 'COVEREDRATIO'
minimum = 0.30
}
excludes = [
'**.dto.**',
'**.event.**',
'**.*InitData*',
'**.*Application*',
'**.exception.**',
'**.service.alarm.**',
'**.aop.**',
'**.config.**',
'**.MemberRole*'
] + QDomainList
}
}
}
JaCoCo 테스트 지정하기
tasks.named('test') {
useJUnitPlatform()
finalizedBy jacocoTestReport
}
SonarQube 분석 실행하기
./gradlew build sonar