본문 바로가기
스프링/만들면서 배우는 실무 백엔드 개발

11. Jacoco + Gradle.kts 로 테스트 커버리지 확인하기 (feat. SonarQube)

by kdohyeon (김대니) 2023. 4. 7.
반응형

Jacoco 는 테스트 커버리지를 확인할 수 있는 라이브러리입니다. 프로젝트 내 작성되어 있는 테스트가 전체 코드의 몇 % 정도를 커버하고 있는지 확인할 수 있습니다. HTML, CSV, XML 등의 형태로 리포트를 만들 수 있으며 SonarQube 등 정적 분석 툴에서 활용할 수도 있습니다. 이번 시간에는 Gradle 프로젝트에서 Jacoco 를 설정하여 테스트 커버리지를 확인하고, 이를 기반으로 SonarQube 에서 정적 분석을 해보겠습니다.


Pull Request: https://github.com/kdohyeon/crypto-labs/pull/20

Jacoco 설정하기

Gradle 설정에 jacoco 플러그인을 추가한다. JacocoReport 와 JacocoCoverageVerification 설정을 아래와 같이 해줄 수 있다.
JacocoReport 는 테스트 커버리지 결과를 html, xml, csv 등 읽을 수 있는 형태로 저장하는 태스크이다. html 로 생성하여 직접 확인해볼 수도 있으며 xml, csv 등으로 저장하여 SonarQube 등 정적 분석 툴에 적용해볼 수도 있다. 또한, 테스트 커버리지를 계산할 때에는 브랜치 커버리지로 계산하도록 설정하였고 최소 테스트 커버리지는 50% 로 설정했다.
JacocoCoverageVerification 은 원하는 최소 테스트 커버리지에 충족하는지를 확인해주는 태스크이다. 예를 들어, 최소한의 브랜치 커버리지를 50% 로 설정하고 싶을 때 활용할 수 있다.

// Line 에서 제공하는 buildRecipePlugin 을 사용함
configureByLabels("kotlin") {
	...
	apply(plugin = "jacoco")
    
    configure<JacocoPluginExtension> {
        toolVersion = Versions.jacoco // 버전 0.8.8 사용
    }

    tasks.withType<JacocoReport> {
        executionData(fileTree(buildDir).include("jacoco/*.exec"))
        reports {
            html.required.set(true) // 직접 확인하기 위해 html 생성
            xml.required.set(true) // sonarqube 에서 활용할 수 있도록 생성
            csv.required.set(false) // 필요없어서 생성하지 않음
        }
    }

    tasks.withType<JacocoCoverageVerification> {
        violationRules {
            rule {
                element = "CLASS"

                limit {
                    counter = "BRANCH"
                    value = "COVEREDRATIO"
                    minimum = "0.5".toBigDecimal() // 브랜치 커버리지를 50% 이상
                }
            }
        }
    }
    ...
}

 

테스트 실행

단위 테스트는 이미 작성되어 있다고 가정을 하고 아래 코멘드를 실행시켜보자.

$ ./gradlew --console verbose test jacocoTestReport jacocoTestCoverageVerification

성공!

테스트 결과는 다음 경로에 html, xml, csv 등의 파일 형태로 확인할 수 있다.

build/reports/jacoco/test/html/index.html

index.html

index.html 파일을 열어보면 테스트 커버리지를 확인할 수 있다.

50% 의 커버리지

만약 최소 커버리지를 70%로 설정하고 테스트를 돌려보면 아래와 같이 에러가 발생한다.

70% 이상을 기대했지만 50%밖에 안되는 브랜치 커버리지

SonarQube 실행

index.html 등의 테스트 커버리지 결과를 기반으로 정적 분석 툴을 이용할 수 있다. 대표적으로 SonarQube 가 있는데, Docker 를 이용하여 로컬에서 SonarQube 를 실행할 수 있다. 아래 명령어로 SonarQube 를 실행해보자 (Docker 가 설치되어 있어야 한다.)

$ docker run -d --name sonarqube -p 9000:9000 sonarqube

SonarQube 실행

OrbStack 를 활용하여 로컬에서 실행된 sonar 도커 컨테이너를 확인할 수 있다.

실행된 SonarQube

localhost:9000 으로 접속하면 로그인 화면이 나타나는데 초기 아이디와 비밀번호는 admin 이다.

초기 로그인 아이디와 비밀번호는 "admin"

비밀번호를 변경하고 로그인을 하면 아래의 초기 화면이 나온다.

초기 화면

작업하고 있는 프로젝트와 SonarQube 를 연결하려면 SonarQube 에서 토큰을 발급받아야 한다. 아래 사진을 참고하여 순서대로 클릭 후 토큰을 발급받자.

  1. 우측 상단의 유저 정보 클릭
  2. Security 탭 클릭
  3. 토큰 생성을 위해 이름, Type, 만료 기한을 입력한다.
    • Name: 아무거나 입력 가능
    • Type: User Token
    • Expires in: Never
  4. 생성 버튼 클릭

Admin 토큰 생성

생성을 하고 나면 Token 값이 발행되는데 이 값을 저장해두어야 한다. 잊어버리면 키를 삭제하고 다시 받아야 한다.

Gradle 에 SonarQube 설정

발급받은 토큰은 Gradle 에서 설정해둘 수 있다. sonar.token 이라는 property 에 넣어두면 된다.
(로컬에서 사용할거니 키는 공유되어도 큰 문제는 안될 것 같다. 나중에 별도 소나큐브 인스턴스를 만들어야 한다면 그 때 토큰을 따로 보관해도 될 것 같고, 그래도 영 불안하면 토큰 만료기한을 따로 두면 된다.)

sonar {
    properties {
        property("sonar.host.url", "http://localhost:9000")
        property("sonar.token", "squ_ae54120c8f09aaded7393d2609bbd2c23979822e")
        property("sonar.sources", "src")
        property("sonar.language", "kotlin")
        property("sonar.sourceEncoding", "UTF-8")
        property("sonar.test.inclusions", "**/*Test.java")
        property("sonar.coverage.jacoco.xmlReportPaths", "${buildDir}/reports/jacoco/test/jacocoTestReport.xml")
    }
}

이렇게 설정을 하고 아래 코맨드를 실행시켜보자. (먼저 jacocoTest 로 리포트 파일이 생성되어 있어야 한다.)

$ ./gradlew test sonarqube

이제 SonarQube (localhost:9000) 로 접속하고 Projects 탭에 접근을 해보면 아래와 같은 화면을 확인할 수 있다. 아직 코드 스멜은 없고 기술 부채도 없다!

SonarQube

참고 자료

반응형

댓글