15. jacoco를 통한 테스트 커버리지 체크
코드 커버리지
코드 커버리지는 소프트웨어의 테스트 케이스가 얼마나 충족되었는지를 나타내는 지표 중 하나이다. 테스트를 진행하였을 때 ‘코드 자체가 얼마나 실행되었느냐’는 것이고, 이는 수치를 통해 확인할 수 있다.
jacoco
Java code coverage의 약자로
junit 테스트의 결과를 바탕으로 커버리지를 결과를 리포트 해주는 툴 입니다.
특히 코드정적분석도구인 sonarqube와 연계하여 사용하는 경우가 많습니다.
앞선 툴들에 대한 자세한 설명은 다른 포스팅에서 진행할 예정입니다. 이번 글은 제 프로젝트에 적용해볼려고 합니다.
1. build.gradle에 jacoco 추가
- plugins에 아래처럼 추가
plugins {
...
id 'jacoco'
}
...
}
추가한 뒤 gradle reload를 진행해주면 verification 에 아래 와 같이 추가됩니다.
2. gradle test 진행
- 위 사진의 test를 더블 클릭하셔도 되고 gradle test 명령어로 하셔도 됩니다.
- test 진행이 완료 되면 build > test 폴더 안에 index.html을 발견하실 수 있습니다.
- 끌어다가 띄우고 크롬을 통해서 열면
- 이런 화면을 확인 하실 수 있습니다. 이건 jacoco가 아니라 그냥 test 결과입니다.
- 이제 jacoco 리포트를 확인해봅시다.
3. jacocoTestReport 실행
- jacocoTestReport를 더블클릭해서 실행해줍니다.
- build > report > jacoco 폴더 안에서 index.html을 확인 하실 수 있습니다. 열어줍니다.
5. 결과 확인
- 원래 전체 결과가 나오는데 생각보다 참혹해서 ㅎㅎㅎ 깨달은 부분만 .... 후후 ..
- 프로젝트 중에 mockito를 이용해서 단위 테스트를 진행하면서 신경을 제일 쓴 service 테스트인대 어디를 안타는 거지 했습니다....
- 내용 확인을 해보니 아래처럼 예외 테스트가 부족했다는 것을 확인 하였습니다.
- 생각해보니 파일 업로드 등 파일 관련 처리를 s3로 옴기고 나서 테스트 코드를 추가하지 않았다는걸 알게되었습니다.
(추가해야지 .....ㅠㅠㅠㅠ)
- 27%? 이게 뭐지 라는 생각으로 확인 해보니 (참혹한 dto 테스트 커버리지 .....)
- Dto에 롬복을 통해서 @Data를 통해서 setter 생성하고 한번도 안써서 생긴 내용 이었습니다 .ㅎ (@Builder 짱짱맨.ㅎ)
- dto 테스트를 추가하면
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
class ProjectResponseDtoTest {
@Test
void projectResponseDtoTest() {
ProjectResponseDto projectResponseDto1 = new ProjectResponseDto();
projectResponseDto1.setProjectId(1L);
projectResponseDto1.setProjectTitle("이름");
projectResponseDto1.setProjectContent("내용");
projectResponseDto1.setProjectPostScript("추신");
projectResponseDto1.setFileUrl("파일 주소");
projectResponseDto1.setFileOriginName("파일 이름");
projectResponseDto1.setProjectLink("프로젝트 링크");
projectResponseDto1.setLevel(1);
projectResponseDto1.setMemberId(1L);
ProjectResponseDto projectResponseDto2 = ProjectResponseDto.builder()
.projectId(1L)
.projectTitle("이름")
.projectContent("내용")
.projectPostScript("추신")
.fileUrl("파일 주소")
.fileOriginName("파일 이름")
.projectLink("프로젝트 링크")
.level(1)
.memberId(1L)
.build();
assertAll(
() -> assertThat(projectResponseDto1).isEqualTo(projectResponseDto2),
() -> assertThat(projectResponseDto1.toString())
.hasToString("ProjectResponseDto(projectId=1, projectTitle=이름, projectContent=내용," +
" projectPostScript=추신, fileUrl=파일 주소, fileOriginName=파일 이름," +
" projectLink=프로젝트 링크, level=1, memberId=1)")
);
}
}
- 테스트 커버리지가 올라가긴합니다만
- 과연 dto를 테스트하는게 의미가 있는지 위와 같은 코드를 작성하는 게 의미가 있는지 등을 생각하게 되면서 jacoco 설정을 찾아보게 되었습니다.
- 저의 경우 dto와 querydsl에 의해 생기는 Q클래스를 제외하도록 특정 디렉토리의 특정 클래스를 제외시키는 방법을 사용하였습니다.( 제가 사용한 방법과 다른 방법 등은 아래 주소에서 확인하실 수 있습니다.)
// build.gradle 에 추가
jacocoTestReport {
dependsOn test // tests are required to run before generating the report
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: [
"com/myintroduce/web/dto/*",
"**/Q*.class"
])
}))
}
}
찾아본 결과 디렉토리, 제외, 최소 테스트 커버리지 % 설정 등 다양한 설정이 가능하다는 것을 알게 되었습니다.
(차후에 공부해야지 .ㅎ)
후기
다른 툴을 적용할 때 후기 같은거 안 적었는데 테스트 코드를 신경 쓴다고 했는데도 불구하고 많이 부족하다는 걸 알게되어서 좋은 경험이었다는 생각이 들어서 적게 되었습니다. 모두 사용을 추천 드립니다 .ㅎ
(저는 이제 테스트 코드 짜러)
Reference
https://www.baeldung.com/jacoco-report-exclude
https://docs.gradle.org/current/dsl/org.gradle.testing.jacoco.tasks.JacocoReport.html
https://techblog.woowahan.com/2661/