약 1개월 반 전에 테스트 개수가 200개였다..
추가적인 기능 개발과 리팩토링을 했더니 단위 테스트도 늘어나서 55개가 늘어난 258개가 되었다.
우리 백엔드 파트는 '지성인' 프로젝트를 시작할 때부터 모든 분기 테스트를 작성하기로 마음 먹었다.
또한 레이어드 아키텍처를 적용해서 각 레이어별 역할을 명확히 했다.
그에 따라 각 기능에 대해서 레이어별로 단위 테스트를 작성했다.
힘들긴 했지만 .. 테스트 코드 덕분에 통해 코드의 품질이 올라갔다고 생각한다.
이쯤되니 우리 프로젝트의 테스트 커버리지는 얼마나 되는지 궁금해졌다.
그래서 GitHub Actions을 통해 JaCoCo 테스트 분석 도구를 적용하기로 했다.
적용
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.9'
id 'io.spring.dependency-management' version '1.1.4'
id "org.asciidoctor.jvm.convert" version "3.3.2"
id 'jacoco' // 추가
}
// ... 생략
// Jacoco 설정 -------------------
test {
finalizedBy jacocoTestReport
useJUnitPlatform()
}
jacoco {
toolVersion = "0.8.8"
}
jacocoTestReport {
dependsOn test
reports {
xml.required.set(true)
}
}
// -------------------
일단 build.gradle에 위 내용대로 추가해주면 된다.
기존 plugins에 jacoco만 추가해주고, 아래 나머지 내용은 새롭게 추가했다.
pr_test.yml
name: PR Test
on:
pull_request:
branches: [ develop ]
permissions: write-all
jobs:
test:
# 실행 환경
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
# JDK 17
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
# ./gradlew 권한 설정
- name: ./gradlew 권한 설정
run: chmod +x ./gradlew
# Gradle 테스트 수행
- name: ./gradlew 테스트
run: ./gradlew --info test
# Jacoco Test Coverage Report
- name: Test Coverage Report
id: jacoco
uses: madrapps/jacoco-report@v1.6
with:
title: Test Coverage Report
paths: ${{ github.workspace }}/build/reports/jacoco/test/jacocoTestReport.xml
token: ${{ secrets.GITHUB_TOKEN }}
min-coverage-overall: 70
min-coverage-changed-files: 70
workflow를 추가한 경로는 위 사진과 같다.
나는 기존 파일 전체 커버리지와 변경된 파일 커버리지에 대해 70% 커버러지를 설정했다.
이제 PR을 통해 확인해보자.
슬프게도 약 73%가 나왔다.
단위 테스트를 열심히 작성해왔기 때문에 적어도 80%는 나올 줄 알았다.
관련 트러블슈팅을 하다가 테스트 커버리지 범위 설정을 발견했다.
마지막 발악으로 설정을 추가해보자.
추가 설정
2가지 설정을 추가로 해주면 된다.
01. 디렉토리 범위 설정
jacocoTestReport {
dependsOn test
afterEvaluate { // report 작성 시 특정 파일 제외
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it,
exclude: ['**/JisunginApplication',
'**/*Request*',
'**/*Response*',
'com/jisungin/config/**',
'com/jisungin/exception/**',
'com/jisungin/infra/**',
'com/jisungin/trace/**'])
}))
}
reports {
xml.required.set(true)
}
}
기존 build.gradle에 afterEvaluate{}를 추가하면 된다.
본인은 실행 클래스, 클래스명에 Request / Response가 들어가는 DTO, 테스트가 필요없는 디렉토리들을 제외시켰다.
순수하게 기능 로직과 관련된 클래스와 디렉토리만 검사하도록 설정했다.
02. Lombok 어노테이션 설정
lombok.addLombokGeneratedAnnotation = true
프로젝트 루트 경로에 lombok.config를 만들고, 위 내용과 같이 작성해준다.
해당 설정은 Lombok이 자동으로 생성하는 메서드에 @Generated를 추가하고, Lombok이 생성한 메서드를 무시하도록 도와준다.
그래서 @Getter, @Builder 같은 코드를 제외하고, 반드시 테스트해야 할 코드만 커버리지 검사에 포함한다.
변경된 설정을 적용했더니 약 85%의 테스트 커버리지가 나왔다.
미래에는 최소 90%를 넘는 테스트 커버리지를 목표로 해보겠다.
그래서..
많은 테스트를 작성했지만 아직 전체를 커버하지 못했다.
물론 완벽한 테스트가 완벽한 프로그램을 만드는 것은 아니다.
하지만 개발자는 테스트 작성을 통해 얻을 수 있는 장점이 많다고 생각한다.
내가 지금 어떤 기능을 개발하고 있는지 명확히 알 수 있고, 협업하는 개발자가 테스트 로직을 통해 기능을 더 쉽게 이해할 수 있다.
이런 점들을 인지하고 코드를 작성한다면 높은 테스트 커버리지는 자동으로 따라올 것이다.
파이팅 ! 😊
'프로젝트' 카테고리의 다른 글
CompletableFuture를 활용한 도서 베스트셀러 저장 성능 개선 (1) | 2024.10.24 |
---|---|
RESTful한 path 설계하기 (0) | 2024.10.05 |
AOP를 통한 유저 인증 정보 미리 주입하기 (0) | 2024.07.23 |
[지성인] 한줄평 좋아요 중복 생성 동시성 문제 (0) | 2024.07.06 |