Overview
- Spring Boot (2 버전)에서 소나큐브(SonarQube), JaCoCo 연동하여 정적 분석
- [Spring Boot 3] 소나큐브(SonarQube), JaCoCo 연동하여 정적 분석
- [Spring] JaCoCo를 통한 Code Coverage 측정
Prerequisite
* Spring Boot 2.7.16
* Java 11
* Gradle 7.1.1
* Sonarqube 3.5.0.2730
* Jacoco 0.8.11
* Docker
테스트 애플리케이션
// 테스트할 간단한 Spring Boot 2버전 코드
$ git clone https://github.com/hyunkwanko/spring-boot-2.x-demo.git
소나큐브(SonarQube) 설치
$ sudo su -
$ mkdir sonarqube && cd sonarqube
// https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html
$ sysctl -w vm.max_map_count=262144
$ vi sonarqube-compose.yml
version: "3"
services:
sonarqube:
image: sonarqube:9.8.0-community # 9.8 이후 버전은 Java 17만 지원
depends_on:
- db
environment:
SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
SONAR_JDBC_USERNAME: sonar
SONAR_JDBC_PASSWORD: sonar
volumes:
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_logs:/opt/sonarqube/logs
ports:
- "9000:9000"
ulimits:
nproc: 65535
nofile:
soft: 262144
hard: 262144
db:
image: postgres:12
environment:
POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonar
volumes:
- postgresql:/var/lib/postgresql
- postgresql_data:/var/lib/postgresql/data
volumes:
sonarqube_data:
sonarqube_extensions:
sonarqube_logs:
postgresql:
postgresql_data:
$ docker-compose -f sonarqube-compose.yml up -d
소나큐브(SonarQube) 프로젝트 생성
Spring Boot에 소나큐브(SonarQube), JaCoCo 연동 (build.gradle)
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.16'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id "org.sonarqube" version "3.5.0.2730"
id "jacoco"
}
sonar {
properties {
property "sonar.projectName", "demo"
property "sonar.projectKey", "demo"
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"
}
}
group = 'sample'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '11'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
// Spring boot
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
// Test
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// Lombok
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
// H2
runtimeOnly 'com.h2database:h2'
}
//tasks.named('test') {
test {
useJUnitPlatform()
finalizedBy 'jacocoTestReport' // test 태스크가 끝난 후 실행
}
// 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
}
}
}
정적 분석 테스트
// gradlew 권한 설정
$ sudo chmod +x gradlew
// gradle build
$ ./gradlew build
// 소나큐브(SonarQube) 프로젝트에서 명령어 확인
$ ./gradlew sonar \
-Dsonar.projectKey={projectKey} \
-Dsonar.host.url={SonarQube URL} \
-Dsonar.login={Token}
성공적으로 Build가 되면 소나큐브(SonarQube)에서 위 그림과 같은 분석 데이터를 확인할 수 있습니다.
JaCoCo도 무사히 연동됐다면 그림처럼 Coverage에 데이터가 확인됩니다.
'Spring' 카테고리의 다른 글
[Spring Boot 3] 소나큐브(SonarQube), JaCoCo 연동하여 정적 분석 (0) | 2024.07.05 |
---|---|
[Spring] JaCoCo를 통한 Code Coverage 측정 (0) | 2024.07.03 |
[Spring] JUnit5 테스트 코드 작성 (0) | 2023.10.06 |
[Spring] HATEOAS 개념 및 장단점 (0) | 2023.08.14 |
[Spring/Java] 정규식을 통한 비속어 필터링 (0) | 2023.05.06 |