Jacoco 커버리지 측정 - KimGyuBek/Threadly GitHub Wiki

Jacoco를 이용한 테스트 커버리지 측정

개요

Threadly 프로젝트는 Jacoco를 사용하여 테스트 커버리지를 측정한다.

테스트 실행 시, 각 모둘벌 커버리지 요약이 콘솔에 자동 출력된다.


커버리지 측정 방법

로컬 환경

# threadly-service
cd threadly-service
./gradlew test

# notification-service
cd notification-service
./gradlew test

테스트 후 콘솔에 모듈별 커버리지 요약을 자동으로 출력한다.

상세 리포트 확인

HTML 형식의 상세 리포트는 각 모듈의 build/reports/jacoco/test/html/index.html 경로에서 확인 가능하다.

(예시: app-api 모듈) threadly-service/threadly-apps/app-api/build/reports/jacoco/test/html/index.html


모듈별 커버리지

주요 지표 설명

  • INSTRUCTION: 바이트코드 명령어 단위로 측정된 커버리지(전체 실행 가능한 명령어 중 실제 실행된 비율)
  • BRANCH: 조건문 분기별 실행 여부를 기준으로 한 커버리지
  • LINE: 소스 코드 한 줄 단위로 측정된 커버리지
  • METHOD: 메서드 중 실제 호출된 메서드 비율
  • CLASS: 전체 클래스 중 테스트 과정에서 로드된 클래스 비율

threadly-service

====================================================================================================
CODE COVERAGE SUMMARY (BY MODULE)
====================================================================================================
MODULE                     INSTRUCTION       BRANCH         LINE       METHOD        CLASS
----------------------------------------------------------------------------------------------------
core-domain                      44.3%        44.4%        53.3%        43.7%        37.5%
core-service                     80.8%        74.4%        80.6%        82.8%        93.1%
threadly-commons                 29.6%        12.9%        42.9%        25.3%        33.3%
adapter-persistence              76.6%        87.5%        79.2%        69.8%       100.0%
adapter-redis                    77.9%       100.0%        75.5%        80.4%       100.0%
adapter-storage                  90.2%       100.0%        85.7%       100.0%       100.0%
adapter-kafka                    14.4%         0.0%        17.7%        16.2%        14.3%
app-api                          88.4%        76.3%        88.7%        84.5%        89.8%
app-batch                         8.5%         3.8%        10.6%        27.3%        41.4%
====================================================================================================

notification-service

====================================================================================================
각 모듈별 Test Coverage
====================================================================================================
MODULE                     INSTRUCTION       BRANCH         LINE       METHOD        CLASS
----------------------------------------------------------------------------------------------------
core-domain                      33.5%         3.3%        60.0%        46.7%        40.0%
core-service                     97.8%        95.7%        97.6%        93.8%        87.5%
core-port                        13.1%         0.0%         8.8%         9.4%         8.3%
notification-commons             53.3%        41.7%        60.0%        53.8%        42.9%
adapter-persistence              29.9%         0.0%        58.2%        48.5%        80.0%
adapter-redis                    54.7%       100.0%        52.9%        55.6%       100.0%
adapter-kafka                    34.4%         9.4%        57.1%        51.5%        80.0%
app-api                          81.6%        47.2%        78.4%        80.6%       100.0%
====================================================================================================

일부 모듈(adapter-persistence, adapter-redis, app-batch 등)은 각 모듈의 단위 테스트만 기준으로 보면 커버리지가 낮게 보이지만 외부 인프라 연동이 필요한 모듈으로서 단위 테스트 보다 app-api 모듈에서의 API 통합 테스트에서 실제 동작을 검증하는 전략을 선택했다.

app-api 모듈의 API 통합 테스트를 통해서 다음이 보장된다.

  • adapter 모듈의 통합 환경에서 실제 요구사항을 충족하며 정상 동작함을 E2E로 검증
  • persistence, storage, redis, kafka 등 외부 자원이 실제 요청 흐름에서 올바르게 연결 됨
  • 단순 실행 여부가 아니라 실제 비즈니스 흐름의 검증이 이루어짐

상세 문서: - 테스트 케이스 목록


CI Workflow에서의 Coverage 확인

GitHub Actions Job Summary를 통한 커버리지 출력

CI 파이프라인에서 테스트가 완료되면, Job Summary 섹션에 각 모듈별 테스트 커버리지가 출력된다.

예시: threadly-service, CI

jacoco_ci_summary


커버리지 제외 패턴

의미 있는 커버리지 지표를 위해서 보일러플레이트, 단순 데이터 객체, 인터페이스 등은 Jacoco 측정 대상에서 제외한다.

테스트 대상에서 제외되는 클래스 패턴은 gradle/jacoco.gradle.kts에 정의되어 있다.

제외 대상
exclude(
    "**/*Application.class",
    "**/*Config.class",
    "**/*Properties.class",
    "**/*Module.class",
    "**/dto/**/*Request.class",
    "**/dto/**/*Response.class",
    "**/dto/**/*Command.class",
    "**/dto/**/*ApiResponse.class",
    "**/*Exception.class",
    "**/ErrorCode.class",
    "**/*Type.class",
    "**/*Status.class",
    "**/port/**/*Port.class",
    "**/port/**/*UseCase.class"
)

결론

커버리지의 수치보다는 통합 환경에서의 실제 기능이 올바르게 작동하는지에 더 집중했으며, 이를 위해 app-api 모듈의 API 기반 E2E 통합 테스트를 통해서 전체 흐름을 테스트하고 검증했다.

다만, 커버리지를 높이기 위해 무분별하게 많은 코드를 exclude 하는 방식은 단순히 테스트 커버리지 수치를 올리기 위한 행위에 불과하다. 따라서 불필요한 보일러 플레이트나 단순 데이터 객체만 제외하고, 실제 로직이 있는 코드들은 모두 커버리지 측정 대상으로 유지하여 수치가 아닌 실질적인 품질 지표를 목표로 했다.


관련 문서


⚠️ **GitHub.com Fallback** ⚠️