자기소개페이지만들기

15. jacoco를 통한 테스트 커버리지 체크

wellbell 2021. 6. 30. 21:21

코드 커버리지

코드 커버리지는 소프트웨어의 테스트 케이스가 얼마나 충족되었는지를 나타내는 지표 중 하나이다. 테스트를 진행하였을 때 ‘코드 자체가 얼마나 실행되었느냐’는 것이고, 이는 수치를 통해 확인할 수 있다.

 

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/