본문 바로가기

TIL(Today I Learned)

TIL-231012(Jacoco로 코드 커버리지 측정(1))

📝오늘 공부한 것

  • 실전프로젝트 - '행동대장' 테스트 코드 공부하기
  • 커리어톤 참여하기
  • 프로그래머스 문제 풀기

 

📌 Jacoco로 코드 커버리지 측정하기

프로젝트 기간에는 테스트코드를 작성할 시간이 부족하기도 했고, 테스트코드를 작성하는 것이 어렵고 시간이 많이 걸린다는 이유로 쉽게 시작하지 못했었다. 그래서 Postman으로 여러 컴포넌트가 잘 연결되어  작동하는지만 확인했었다.
테스트 코드를 작성하면 코드 수정 시 예상하지 못했던 부작용을 방지할 수 있다. 또, 개발자 간의 협업을 원활하게 하고, 소프트웨어를 유지 보수하는데 필요한 문서화 작업을 줄일 수 있다.

 실전프로젝트의 테스트코드를 작성하여 단위테스트를 진행해보려고 한다. 각 메서드가 예상대로 작동하는지를 확인함으로써, 코드 변경 또는 업데이트 시 기존 기능들이 올바르게 작동하는지를 검증할 것이다.
이번에 직접 테스트 코드를 작성해 보며 그 장단점을 느끼고, 이 경험을 바탕으로 다음 프로젝트에 반영하고자 한다.

테스트코드를 처음 작성하는 만큼, 가장 많이 이용하고 레퍼런스가 가장 많은 Jacoco를 선택하기로 하였다.

 

[ Jacoco 설정하기 ]

JaCoCo란?

Java 코드의 커버리지를 체크하는 라이브러리

테스트코드를 돌리고 그 커버리지 결과를 눈으로 보기 좋도록 html이나 xml, csv 같은 리포트로 생성

 

 

JaCoCo 플러그인 추가

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.1.2'
    id 'io.spring.dependency-management' version '1.1.2'
    id 'jacoco' // jacoco 추가!!
}

tasks.named('test') {
    useJUnitPlatform()
    finalizedBy jacocoTestReport
}

jacoco {
    toolVersion = "0.8.10"
    // jacoco 리포트 디렉토리 설정
    reportsDirectory = layout.buildDirectory.dir("$buildDir/reports/jacoco")
}
  • JaCoCo의 버전은 현재 가장 최신 버전인 0.8.10을 선택하였다.
  • 'test'작업이 완료되면 'jacocoTestReport'작업을 실행할 수 있도록 'finalizedBy jacocoTestReport'를 작성하였다.
    이는 테스트가 실행된 후 코드 커버리지 리포트를 생성하게 한다.

 

Gradle task 설정 - 테스트 리포트 저장과 커버리지 체크

JaCoCo 플러그인에는 'jacocoTestReport'와 'jacocoTestCoverageVerification' 두 가지의 task가 있다.

 

jacocoTestReport

  • 바이너리 커버리지 결과를 사람이 읽기 좋은 형태의 리포트로 저장하는 task
  • html파일로 생성해 사람이 쉽게 눈으로 확인할 수도 있고, SonarQube 등으로 연동하기 위해 xml, csv 같은 형태로도 리포트를 생성할 수 있다.
jacocoTestReport {
    reports {
    //html타입의 리포트 형태만 생성
        xml.required = false;
        csv.required = false;
        //리포트의 저장경로 설정
        html.outputLocation = layout.buildDirectory.dir("$buildDir/reports/html-report")
    }
    
    //모든 설정이 완료된 후 실행될 코드 목록
    afterEvaluate {
        //클래스 디렉토리 설정
        getClassDirectories().setFrom(classDirectories.files.collect {
            fileTree(dir: it, exclude:  [
                    "**/*Controller*",
                    "**/*Config*",
                    "**/*ActionBossApplication*",
                    "**/*Builder*",
                    "**/*Exception*",
                    "**/*MyPagePostService*",
                    "**/*notification*",
                    "**/*post*",
                    "**/*search*",
                    "**/*MyPagePostsResponseDto*",
                    "**/*PagingResponseDto*"
            ])
        })
    }

    finalizedBy jacocoTestCoverageVerification
}
  • 클래스 디렉토리에서 테스트를 하기 힘든 controller, config들을 제외하였고,
    프로젝트에서 내가 작성하지 않은 코드들(내가 담당한 기능이 아닌 코드들)은 제외시켰다.
  • 'finalizedBy jacocoTestCoverageVerification'을 추가하여 jacocoTestReport가 종료된 후 jacocoTestCoverageVerification라는 task가 진행되도록 하였다.

 

jacocoTestCoverageVerification

  • 내가 원하는 커버리지 기준을 만족하는지 확인해 주는 task이다.
  • 클래스 커버리지를 최소한 90% 이상으로 유지하고 싶다면, 이 task에 설정하면 된다.
    test task처럼 Gradle빌드의 성공/실패로 결과를 보여준다.
jacocoTestCoverageVerification {
    violationRules {
        rule {
            element = "CLASS"

            limit {
                counter = "INSTRUCTION"
                value = "COVEREDRATIO"
                minimum = 0.90
            }

            limit {
                counter = "BRANCH"
                value = "COVEREDRATIO"
                minimum = 0.90
            }

            excludes = [
                    "**.*Builder",
                    "**.ActionBossApplication",
                    "**.*Config",
                    "**.*Controller",
                    "**.*Exception*",
                    "**.*MyPagePostService*",
                    "**.*notification*",
                    "**.*post*",
                    "**.*search*",
                    "**.*MyPagePostsResponseDto*",
                    "**.*PagingResponseDto*"
            ]
        }
    }
}
  • 커버리지 카운터 유형 INSTRUCTION, BRANCH, LINE, COMPLEXITY, METHOD, CLASS 중 INSTRUCTION과 BRANCH를 선택하였다.
  • 최소 커버리지 기준은 0.90으로 설정하였다.
  • Controller, Config 등의 특정 클래스는 검증에서 제외하는 것으로 설정해 주었다.
✔ 최소 커버리지 기준 90% 설정 이유
일반적으로 많은 곳들이 80% 이상의 코드 커버리지를 목표로 설정한다고 한다. 반면, 로버트 마틴은 테스트 커버리지 100%는 권장이 아니라 강력히 요구되는 사항이라고 한다. 이번에 처음으로 테스트코드를 작성하는 만큼, 100%는 아니지만 그래도 높은 수치인 90%의 커버리지를 목표로 해보려고 한다.

 

설정 완료 후 Build

build가 실패했다.

커버리지를 최소 0.90으로 설정했기 때문이다.

메시지를 보면 커버리지 비율이 0.25, 0.00, 0.08등으로 최소 0.90을 넘지 않아 실패했음을 알 수 있다.

 

생성된 리포트를 크롬창으로 열어 확인해 보면 커버리지를 확인할 수 있다.

목표 : Total 코드 커버리지 90% 이상 달성하기

 

이제부터 커버리지 100%를 채운다는 생각으로 테스트코드를 열심히 작성해 봐야겠다!!!

 

 

 

references:
https://medium.com/@AyushVardhan/enforcing-code-coverage-rule-with-jacoco-in-maven-lifecycle-8ebc1fe3b6ce

https://techblog.woowahan.com/2661/

https://hudi.blog/code-coverage/

 

Jacoco 설정하기
👉🏻 2023.10.12 - [TIL(Today I Learned)] - TIL-231012(Jacoco로 코드 커버리지 측정(1))
테스트 실행 시 예외 메시지를 가져오지 않음
👉🏻 2023.10.13 - [TIL(Today I Learned)] - TIL-231013(테스트 실행 시 예외 메시지를 가져오지 않는 문제)
의미 있는 테스트 코드 작성이란 무엇일까..
👉🏻 2023.10.17 - [TIL(Today I Learned)] - TIL-231017(Jacoco로 코드 커버리지 측정(2))
테스트 코드 결과
👉🏻 2023.10.18 - [TIL(Today I Learned)] - TIL-231018(Jacoco로 코드 커버리지 측정(3))