궁금증

코드 커버리지(Code Coverage)란 무엇일까?

0and24 2024. 12. 16. 14:46

오늘 코드를 테스트하면서 "내가 작성한 테스트가 얼마나 효과적으로 작동하고 있을까?"라는 생각이 들었습니다. 이 질문에 답을 찾던 중, 코드 커버리지(Code Coverage)라는 개념을 알게 되었고, 이를 공부하며 배운 점들을 정리해 보았습니다.


1. 코드 커버리지란?

코드 커버리지는 테스트 코드가 애플리케이션의 소스 코드를 얼마나 실행했는지를 측정하는 지표입니다. 즉, "테스트가 코드의 몇 퍼센트를 실행했는가?"를 숫자로 나타내는 도구라고 이해하면 됩니다.

  • 예를 들어, 100줄짜리 코드 중 테스트가 70줄을 실행했다면, 코드 커버리지는 70%입니다.

코드 커버리지를 측정하면 아래와 같은 질문에 답을 얻을 수 있습니다:

  • 테스트가 코드의 중요한 부분을 충분히 검증하고 있는가?
  • 테스트되지 않은 코드가 존재하는가?

2. 코드 커버리지를 왜 사용하는가?

처음에는 "테스트가 잘 작동하면 그만 아닌가?"라고 생각했지만, 코드 커버리지를 사용하는 이유를 알게 되니 생각이 조금 달라졌습니다. 코드 커버리지는 아래와 같은 이유로 유용합니다:

1) 테스트의 신뢰성을 높임

테스트는 코드의 동작을 확인하는 도구입니다. 하지만 테스트가 코드의 일부만 실행한다면 중요한 부분이 누락될 수 있습니다. 코드 커버리지를 확인하면 테스트가 얼마나 철저하게 작성되었는지 알 수 있어 테스트의 신뢰성을 높일 수 있습니다.

2) 테스트의 사각지대 발견

코드 커버리지 도구를 사용하면 테스트되지 않은 코드가 어디인지 쉽게 알 수 있습니다. 이를 통해 테스트의 사각지대를 보완하고 더 견고한 코드를 작성할 수 있습니다.

3) 유지보수와 디버깅에 도움

테스트를 통해 많은 코드를 실행하고 검증할수록, 이후에 문제가 발생했을 때 디버깅이 더 쉬워집니다. 특히, 복잡한 시스템에서 코드 커버리지는 유지보수를 간편하게 만들어 줍니다.


3. 코드 커버리지의 종류

코드 커버리지를 측정하는 방법에는 여러 가지가 있습니다. 각각의 방식은 테스트가 코드를 얼마나 꼼꼼히 검증하고 있는지를 다른 관점에서 보여줍니다.

1) 라인 커버리지 (Line Coverage)

  • 코드의 각 줄이 테스트에서 실행되었는지를 확인합니다.
  • 100줄 중 70줄이 실행되었다면, 라인 커버리지는 70%입니다.

2) 브랜치 커버리지 (Branch Coverage)

  • 조건문(if, switch)의 각 분기가 테스트에서 실행되었는지를 확인합니다.
  • 예를 들어, if (x > 10) 조건에서 x > 10일 때와 아닐 때 두 가지 경우가 모두 테스트되었는지 확인합니다.

3) 함수 커버리지 (Function Coverage)

  • 함수 또는 메서드 단위로 테스트가 실행되었는지를 확인합니다.

4) 스테이트먼트 커버리지 (Statement Coverage)

  • 코드의 각 명령문(Statement)이 실행되었는지를 확인합니다.

4. 코드 커버리지를 무조건 높이면 좋은 걸까?

공부하면서 알게 된 중요한 사실 중 하나는 코드 커버리지가 높다고 해서 반드시 좋은 테스트가 보장되는 것은 아니라는 점입니다.

1) 테스트의 질이 더 중요

코드 커버리지가 100%라 하더라도, 테스트 자체가 제대로 작성되지 않았다면 의미가 없습니다. 예를 들어, 단순히 코드 실행만 확인하는 테스트는 코드 커버리지를 높이지만, 실제로 코드의 로직을 검증하지 않기 때문에 버그를 찾을 수 없습니다.

2) 현실적인 목표 설정

현실적으로 모든 프로젝트에서 코드 커버리지 100%를 목표로 하기에는 시간과 리소스가 부족할 수 있습니다. 따라서, 중요한 비즈니스 로직과 에러 가능성이 높은 부분에 테스트를 집중하는 것이 더 효율적입니다.


5. 코드 커버리지를 측정하는 방법 (IntelliJ Community Edition 기준)

IntelliJ IDEA 무료 버전에서도 JUnit 테스트를 통해 코드 커버리지를 측정할 수 있습니다.

커버리지 실행 방법:

  1. 테스트 폴더나 클래스 파일을 우클릭합니다.
  2. More Run/Debug > Run 'Tests ... with Coverage 옵션을 선택합니다.
  3. 테스트가 실행되면 Coverage 리포트가 하단에 표시됩니다.

커버리지 리포트 예시:

  • 초록색: 테스트가 실행된 코드
  • 빨간색: 테스트되지 않은 코드

리포트 화면:

이 결과를 통해 테스트가 부족한 부분을 쉽게 파악하고 보완할 수 있습니다.

실행 후 결과


6. 코드 커버리지를 높이기 위한 테스트 작성법

1) 조건문과 분기 테스트 강화

조건문이 있는 로직의 모든 분기를 테스트합니다:

@Test
void testGetGrade() {
    MyService service = new MyService();
    assertEquals("A", service.getGrade(95)); // 조건 1
    assertEquals("B", service.getGrade(85)); // 조건 2
    assertEquals("C", service.getGrade(70)); // 조건 3
}

 

2) 예외 상황 테스트 추가

예외가 발생하는 경우도 반드시 테스트해야 합니다:

@Test
void testGetGradeWithInvalidInput() {
    MyService service = new MyService();
    assertThrows(IllegalArgumentException.class, () -> service.getGrade(-1));
}

3) Mocking을 활용한 단위 테스트

외부 의존성이 있는 클래스는 Mock 객체를 사용해 단위 테스트를 작성합니다:

@Mock
private NoticeRepository noticeRepository;

@InjectMocks
private NoticeService noticeService;

@Test
void testFindNotice() {
    Notice notice = new Notice(1L, "Title", "Content");
    when(noticeRepository.findById(1L)).thenReturn(Optional.of(notice));
    
    NoticeDto result = noticeService.getNotice(1L);
    assertEquals("Title", result.getTitle());
}

7. 느낀 점

코드 커버리지는 단순히 "테스트가 얼마나 실행되었는가?"를 넘어, 테스트의 방향성과 품질을 점검하는 중요한 도구라는 생각이 들었습니다. 물론 커버리지를 높이는 것도 중요하지만, 실제로 코드를 검증하는 테스트를 작성하는 것이 더 중요하다는 점도 배웠습니다.

앞으로 프로젝트를 진행하면서 코드 커버리지 리포트를 적극적으로 활용해 테스트의 빈틈을 찾고, 더 견고한 코드를 작성할 수 있도록 노력해야겠다는 생각이 들었습니다. 생각보다 많은 인사이트를 얻을 수 있을 것 같습니다.

 

참고 자료:

https://www.jetbrains.com/help/idea/code-coverage.html#read_the_coverage_data

 

Code coverage | IntelliJ IDEA

 

www.jetbrains.com