메뉴 여닫기
환경 설정 메뉴 여닫기
개인 메뉴 여닫기
로그인하지 않음
지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.

코드 커버리지

noriwiki
(Code coverage에서 넘어옴)


개요

코드 커버리지(Code Coverage)는 소프트웨어 테스팅에서 테스트가 소스 코드의 어느 정도를 실행했는지를 측정하는 메트릭이다. 이를 통해 테스트의 효과를 평가하고, 테스트가 코드의 주요 부분을 충분히 검증하고 있는지 판단할 수 있다. 코드 커버리지는 주로 테스트의 완전성을 확인하기 위해 사용되며, 실행되지 않은 코드를 기반으로 추가적인 테스트를 설계할 수 있다.

주요 유형

  • 문 커버리지 (Statement Coverage)

코드의 각 문(statement)이 실행되었는지를 측정한다. 예를 들어, if-else 구문에서 ifelse 블록이 모두 실행되었는지를 확인한다.

    • 장점: 간단하고 빠르게 측정할 수 있다.
    • 단점: 조건의 모든 경우를 보장하지는 못한다.
  • 엣지 커버리지 (Edge Coverage)

Control flow graph하의 모든 Edge들을 참색했는지 측정한다.

  • 분기 커버리지 (Branch Coverage)

분기 커버리지는 엣지 커버리지의 한 종류로써, 조건문(if, switch)에서 모든 분기(branch)가 실행되었는지를 확인한다. 예를 들어, if (x > 0) 구문에서 x > 0의 참과 거짓인 경우가 모두 테스트되었는지 확인한다.

    • 장점: 모든 논리 경로를 확인하므로 더 높은 신뢰도를 제공한다.
    • 단점: 복잡한 조건문이 많을 경우 테스트 설계가 어려워질 수 있다.
  • 조건 커버리지 (Condition Coverage)

복합 조건문(예: if (A && B))에서 각 개별 조건(A, B)이 참과 거짓인 경우를 테스트했는지 확인한다.

  • 함수 커버리지 (Function Coverage)

코드의 모든 함수가 실행되었는지를 확인한다.

    • 장점: 모듈 수준에서 테스트 진행 상황을 빠르게 파악할 수 있다.
    • 단점: 함수 내부의 세부 동작은 확인하지 못한다.
  • 결정 커버리지 (Dicision Coverage

코드의 모든 Return statement가 실행되었는지를 측정한다. Dicision Coverage는 Function Coverage와 Branch Coverage를 동시에 측정한다.

  • 경로 커버리지 (Path Coverage)

프로그램 내의 모든 가능한 실행 경로를 테스트한다.

    • 장점: 테스트의 완전성이 매우 높다.
    • 단점: 실행 경로가 많아질수록 계산량이 급격히 증가한다.
  • 루프 커버리지 (Loop Coverage)

루프 구조(for, while)에서 모든 반복 경로를 테스트한다. 예를 들어, 루프가 0회, 1회, N회 반복되는 경우를 확인한다.

이외에도, Linear Code Sequence and Jump (LCSAJ)커버리지, Entry/exit coverage, State coverage, Data-flow coverage와 같은 다양한 방법들로 Code Coverage를 측정할 수 있다.

이 Coverage들중에서 Statement coverage(C1)과 Branch or condition coverage(C2)가 제일 많이 사용되는 Coverage로써, 대다수의 상용 프로그램들은 C1혹은 C2커버지리를 바탕으로 Software analysis의 성능을 평가한다. C1과 C2를 같이 사용하면 대다수의 statement를 커버할 수 있어서, 자연스럽게 function, loop, path, state, control flow등등의 Coverage를 평가할 수 있다.

장점

  • 테스트가 코드의 중요한 부분을 놓치지 않도록 도와준다.
  • 디버깅 과정을 용이하게 한다.
  • CI/CD 파이프라인에서 코드 커버리지 도구와 통합하여 자동으로 테스트의 효과를 평가할 수 있다.
  • 충분히 테스트된 코드베이스는 유지보수가 용이하며, 안정성을 유지할 가능성이 높다.

한계

  • 높은 커버리지가 항상 높은 품질을 의미하지 않는다. 코드가 실행되었더라도 테스트가 코드의 정확한 동작을 검증했는지는 보장하지 않는다. 따라서, 커버리지 수치만을 목표로 삼는 것은 위험할 수 있으므로, 테스트 케이스의 품질과 함께 활용하는 것이 중요하다.
  • 높은 커버리지를 달성하려면 많은 테스트 케이스와 시간이 필요하다. 예를 들어서 Full path coverage은 달성하기 힘든 과제이다. 예를 들어서 n개의 decision이 있는 프로그램의 경우 [math]\displaystyle{ 2^n }[/math]개의 path를 측정해야 하기 때문에, 필요한 시간이 기하급수적으로 증가한다.
  • 복잡한 프로그램에서는 모든 실행 경로를 테스트하는 것이 현실적으로 어렵다. 일례로, 만약 Full path coverage를 달성할 수 있다는 것은 Halting problem을 해결 가능하다는 말과 동치이다. 즉 현실적으로 프로그램의 모든 것을 측정하는 완전무결한 Code coverage는 존재할 수 없다.

도구

다양한 도구들이 코드 커버리지를 측정하기 위해 사용된다:

  • Python: coverage.py
  • Java: JaCoCo, Cobertura
  • C/C++: gcov, LCOV
  • JavaScript: Istanbul, NYC
  • CI/CD 도구: Jenkins, GitLab, CircleCI 등에서 코드 커버리지를 지원한다.