Spring

[Spring] JaCoCo를 통한 Code Coverage 측정

테런 2024. 7. 3. 16:24
Overview
  • Spring Boot에서 JaCoCo를 통한 Code Coverage 측정

 

Prerequisite
* Spring Boot 3.2.7 (Spring Boot 2 버전도 동일하게 적용 가능합니다.)
* Java 17
* Gradle 8.1
* Jacoco 0.8.11

 

JaCoCo 개념
JaCoCo(Java Code Coverage)는 Java 언어로 작성된 프로그램의 코드 커버리지를 측정하는 도구입니다. 코드 커버리지는 소프트웨어 테스트의 품질을 측정하는 데 사용되며, 특히 자동화된 테스트 스위트에서 테스트가 코드베이스의 얼마나 많은 부분을 실행했는지를 보여줍니다.

JaCoCo는 다음과 같은 주요 기능을 제공합니다.

1. 라인 커버리지(Line Coverage): 소스 코드의 각 라인이 실행된 횟수를 기록하여 얼마나 많은 라인이 실행되었는지를 보여줍니다.
2. 브랜치 커버리지(Branch Coverage): 조건문(if, switch 등)의 각 분기(branch)가 실행된 횟수를 측정하여 조건 분기의 테스트 커버리지를 보여줍니다.
3. 메소드 커버리지(Method Coverage): 각 메소드가 호출된 횟수를 측정합니다.
4. 클래스 커버리지(Class Coverage): 클래스가 인스턴스화된 횟수를 측정합니다.
5. 명령줄 도구(Command Line Tool): JaCoCo는 명령줄에서 실행할 수 있는 독립형 도구로 제공되며, 빌드 시스템과 연동하여 테스트 수행 후 커버리지 보고서를 생성할 수 있습니다.
6. IDE 통합(Integration with IDEs): 대부분의 주요 IDE(Integrated Development Environment)에서 JaCoCo 플러그인을 제공하여 손쉽게 코드 커버리지를 확인할 수 있습니다.

JaCoCo는 오픈 소스 프로젝트로, Apache License 2.0 하에 배포되며, Maven, Gradle 등 다양한 빌드 도구와 통합하여 사용할 수 있습니다. 코드 커버리지를 통해 어플리케이션의 테스트 품질을 평가하고, 테스트되지 않은 부분을 식별하여 품질을 향상시키는 데 도움을 줍니다.

 

JaCoCo 적용 (build.gradle)
plugins {
	id 'java'
	id 'org.springframework.boot' version '3.2.7'
	id 'io.spring.dependency-management' version '1.1.5'
	id "jacoco"
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
	toolchain {
		languageVersion = JavaLanguageVersion.of(17)
	}
}

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'
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

	// Lombok
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'

	// H2
	runtimeOnly 'com.h2database:h2'
}

tasks.named('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
		}
	}
}

build.gradle 작성 후 > 오른쪽 Gradle > Execute Gradle Task > gradle test

 

build > reports > jacoco > test > html > index.html

 

index.html 브라우저로 열기

 

이상적인 코드 커버리지 비율
코드 커버리지율은 소프트웨어 테스트의 품질을 측정하는 중요한 지표입니다. 하지만 이상적인 코드 커버리지율은 프로젝트의 성격과 요구사항에 따라 다를 수 있습니다. 일반적으로 코드 커버리지율에 대한 일반적인 기준은 다음과 같습니다.

1. 라인 커버리지(Line Coverage): 최소 80% 이상을 추천합니다. 이는 소스 코드의 대다수 라인이 실행되었음을 의미하며, 대부분의 경험적인 데이터에서 이 수치는 코드의 대다수 오류를 찾아내는 데 충분하다고 알려져 있습니다.

2. 브랜치 커버리지(Branch Coverage): 최소 70% 이상을 추천합니다. 조건문(if, switch 등)의 각 분기가 충분히 테스트되었는지를 나타내며, 이는 프로그램의 분기 조건을 다양한 상황에서 테스트했는지를 확인하는 데 도움이 됩니다.

3. 메소드와 클래스 커버리지(Method & Class Coverage): 일반적으로 라인과 브랜치 커버리지에 비해 높은 수치가 필요하지는 않지만, 전체적인 커버리지를 향상시키는 데 도움이 됩니다. 보통 70% 이상을 추천합니다.

이러한 기준은 프로젝트의 규모, 중요도, 품질 요구사항 등에 따라 다를 수 있으며, 일부 프로젝트에서는 더 높은 커버리지율을 목표로 할 수도 있습니다. 또한, 코드 커버리지는 단지 테스트의 품질을 측정하는 지표일 뿐, 테스트의 품질이나 완성도를 전적으로 보장하지는 않습니다. 따라서 테스트는 전반적인 품질 보증 프로세스의 일환으로 고려되어야 합니다.