JaCoCo : Java Code Coverage

Sixhustle·2020년 10월 6일
0

Spring

목록 보기
2/10

Java 프로젝트의 Code coverage를 측정할 수 있는 JaCoCo 적용해보겠습니다.

Version

SpringBoot : 2.3.4
Gradle : 6.6.1


build.gradle

아래의 내용은 모두 build.gradle에 작성된 것입니다.

plugins 추가

plugins {
	...
    id 'jacoco'
}

jacoco {
   toolVersion = '0.8.5'	
   reportsDir = "${project.reporting.baseDir}/jacoco"
}

jacoco plugin을 추가하면, Gradle/Tasks/verification탭을 보면 jacocoTestReport, jacocoTestCoverageVerification이 생성된 것을 확인할 수 있습니다.

KeyDescription
versionJaCoCo 버전으로 기본값은 Latest입니다.
reportsDir테스트결과 리포트 저장 경로입니다. 위에 명시된 값이 기본 경로입니다.

jacocoTestReport

jacocoTestReport {
    reports {
        html.enabled true
        csv.enabled false
        xml.enabled false
    }
    finalizedBy 'jacocoTestCoverageVerification'
}

jacocoTestReport는 바이너리로 된 커버리지 결과를 사람이 읽기 좋은 형태로 저장합니다. html, csv, xml으로 제공됩니다.
finalizedBy은 gradle명령어로 "jacocoTestReport를 실행하고, jacocoTestCoverageVerification을 실행시키겠다." 는 의미입니다. report결과가 개발자가 설정한 검증 수준을 넘었는지 확인할 때 사용할 수 있습니다.


jacocoTestCoverageVerification

jacocoTestCoverageVerification {
   violationRules {
      rule {
         // CLASS단위로, Line CoverateRatio가 60% 이상이어야 한다.
         enabled = true
         element = 'CLASS'
         limit {
            counter = 'LINE'
            value = 'COVEREDRATIO'
            minimum = 0.60
         }
         
         // CLASS단위로, 빈 줄을 제외한 Line수를 최대 200으로 제한한다.
         limit {
            counter = 'LINE'
            value = 'TOTALCOUNT'
            maximum = 200
         }
      }
   }
}

Code Coverage를 검증 수준을 정의하는 부분입니다. 설정한 수준에 달성하지 못하면, task는 실패하게 됩니다.
violocationRules에 다수의 rule을 정의할 수 있고, 하나의 rule이라도 만족하지 못하면, task는 실패합니다.

아래는 JaCoCoLimit의 내용을 간략하게 정리한 것입니다.

element

Coverage의 기준이 되는 값입니다.
BUNDLE : Default
PACKAGE
CLASS
SOURCEFILE
METHOD

counter

아래의 조건으로 코드를 수치화 합니다.
INSTRUCTION : Default, Java 바이트 코드 명령 수 입니다.
LINE : 빈 줄을 제외한 라인 수
BRANCH : 조건 문 등의 분기 수
CLASS : 클래스 수
METHOD : 메소드 수
COMPLEXITY : 복잡도(계산법)

value

counter로 수치화 된 값이 maximum/minimum에 충족하는지 확인하기 위한 조건입니다.
COVEREDRATIO : Default, 커버된 비율로 0~1사이의 double값으로 1이 100%입니다.
MISSEDRATIO : 커버되지 않은 비율
TOTALCOUNT : 전체 개수
MISSEDCOUNT : 커버되지 않은 수
COVEREDCOUNT : 커버된 수

minimum / maximum

이 값은 BigDecimal로 개발자가 지정한 유효자리까지만 표시되고, 자리수가 넘어가면 반올림 됩니다.
예를들어, minimum = 0.80이면, 0.7이 아닌 0.74로 표시됩니다.


test

test {
    useJUnitPlatform()
    finalizedBy 'jacocoTestReport'
}

useJUnitPlatform()은 JUnit을 사용하겠다고 Gradle에 알려주는 것으로 JUnit으로 Test Code를 작성했을 경우 필수입니다.

먼저, jacocoTestReport에서도 finalizedBy 'jaCocoTestCoverageVerification'을 선언했기 때문에 finalizedBy테스트가 수행될 때마다 report를 생성하고, Code coverage 검증을 수행하는 설정입니다.

exclude

jacocoTestCoverageVerification {
   violationRules {
      rule {
         ...
         excludes = [
         	'*.common.*'
         ]
      }
   }
}

excludes로 테스트에서 제외할 패키지/클래스를 설정할 수 있습니다.

Run test

./gradlew clean test
> Task :test
2020-10-07 00:22:34.778  INFO 3988 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

> Task :jacocoTestCoverageVerification FAILED
[ant:jacocoReport] Rule violated for class com.sixhustle.jacoco.Application: lines covered ratio is 0.33, but expected minimum is 0.80
[ant:jacocoReport] Rule violated for class com.sixhustle.jacoco.JacocoController: lines covered ratio is 0.50, but expected minimum is 0.80

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':jacocoTestCoverageVerification'.
> Rule violated for class com.sixhustle.jacoco.Application: lines covered ratio is 0.33, but expected minimum is 0.80
  Rule violated for class com.sixhustle.jacoco.controller.JacocoController: lines covered ratio is 0.50, but expected minimum is 0.80

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 4s
7 actionable tasks: 7 executed

./gradlew clean test명령어로 test > jacocoTestReport > jacocoTestCoverageVerification순으로 task가 실행됩니다.

위는 Test수행 결과Lines covered ratio가 0.33인데, 기대하는 minimum ratio는 0.80이라 Test Fail(Build Failed)한 예제입니다.


build.gradle

build.gradle 전체 파일입니다.

plugins {
    id 'org.springframework.boot' version '2.3.4.RELEASE'
    id 'io.spring.dependency-management' version '1.0.10.RELEASE'
    id 'java'
    id 'jacoco'
}

group = 'com.sixhustle'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}

test {
    useJUnitPlatform()
    finalizedBy 'jacocoTestReport'
}

jacoco {
    toolVersion = '0.8.5'
}

jacocoTestReport {
    reports {
        html.enabled true
        csv.enabled false
        xml.enabled false
    }
    finalizedBy 'jacocoTestCoverageVerification'
}

jacocoTestCoverageVerification {
    violationRules {
        rule {
            enabled = true
            element = 'CLASS'
            limit {
                counter = 'LINE'
                value = 'COVEREDRATIO'
                minimum = 0.80
            }
        }
    }
}

References

0개의 댓글