4 분 소요

이번 포스트에서는 V&V (Verification and Validation) 에 대해 다룬다. 그리고 White Box Coverage 에 대해 자세히 다루려고 한다.

V&V (Verification and Validation)

V&V 란?

  • 소프트웨어 개발 생명주기 전체에 걸쳐서 수행되는 과정
  • 목적
  1. Verification
    • 개발 프로세스의 각 단계가 올바르게 수행되었는가?
    • 주로 검토 (Inspection), 리뷰 (review) 중심으로 이루어진다.
  2. Validation
    • 산출물이 이전 단계의 요구사항을 충족하는가?
    • 주로 testing 중심인 동적 방법으로 검증한다.

Insepction

  • 정적 시스템 표현 분석 => 문제 발견
  • 시스템을 실행하지 않아도 검증이 가능하다.
    • 요구사항 문서, 설계 문서, 구성 데이터, 테스트 데이터 등에도 적용이 가능하다.
  • 장점

BKM (Best Known Method) : 설계 및 코드의 50~90%의 결함을 제거할 수 있다.

이는 곧 테스트 비용을 절감해준다. => 테스트 대비 경제적 효과가 크다.

Program Testing

  • 동적 검증
  • 프로그램이 의도한 기능을 수행하는지를 검증한다.
  • 실험을 통해서 오류를 발견한다.
  • 핵심 : 오류의 존재는 검증이 가능하지만, 부재는 보장이 불가하다.

Inspections 과 Testing은 상호보완적으로 사용해야 한다.

-> V&V는 두 가지의 접근이 모두 활용이 필요하기 때문이다.

Testing Stages

  • 소프트웨어 테스트는 단계적으로 수행된다.
단계 목적
Development Testing 개발자가 수행 → 초기 결함 제거
Release Testing 시스템 버전 테스트 → 고객 요구사항 충족 검증
User Testing 실제 사용 환경에서 고객/사용자가 테스트

Development Testing

  • 개발 단계 테스트로 주로 개발자가 수행한다.
  • 목적은 크게 2가지이다.
    • 프로그램 오류를 검출한다.
    • 요구사항을 충족하는지 검증한다.
  • 3가지의 주요 테스트를 수행한다.
1. Unit Testing

프로그램의 개별 구성요소 (함수, 클래스 등)를 테스트 한다.

2. Component Testing

여러 유닛을 결합한 컴포넌트 단위를 테스트 한다.

3. System Testing

전체 시스템이 요구사항을 충족하는지 테스트 한다.

개발 단계에서 점진적으로 테스트 범위를 넓혀가는 구조이다.

Black box vs Whit box Testing

Black box Testing

  • 테스트를 진행할 때 시스템 내부 구조를 고려하지 않는다.
  • 입력 -> 출력 결과만 보고 테스트를 수행한다.

  • 설계 명세기반으로 테스트하여 요구사항이 충족하는지에 대한 여부를 확인하는데 용이하다.
  • 사용자의 관점에서 테스트 가능

주로 기능 테스트, 요구사항 기반 테스트에서 사용된다.

White box Testing

  • 테스트 시 시스템 내부 구조를 고려하여 테스트를 설계한다.
  • 모든 경로/ 조건 등을 고려해 구현 코드를 기반으로 테스트를 설계한다.
  • 경로 커버리지 확보가 가능하여 숨겨진 내부 오류를 검출할 수 있다.

  • 단점: 테스트 비용이 높아지고, 내부 구현 변경시 테스트 케이스도 변경해야 한다.

주로 단위 테스트, 개발자 테스트에서 활용한다.

Equivalence Partitioning

  • 등가 분할 테스트
  • 입력 값의 범위 전체를 테스트 하는 것은 불가능하다.
    • 너무 많은 경우의 수가 존재하기 때문이다.
  • 동일하게 동작할 것 같은 그룹을 나눈다. (Partitioning)
  • 각 그룹에서 대푯값만 선택하여 테스트 한다.

더 효율적으로 테스트 케이스를 줄이고 테스트를 할 수 있다.


Test Coverage (for White Box Testing)

Code Coverage란?

  • 테스트가 소스 코드의 얼마만큼을 실행했는지를 측정하는 지표

  • 작성한 테스트 케이스(Test Suite)가 소스 코드의 어느 부분까지 실행/검증했는지를 보는 것

  • 왜 중요할까?

    • 테스트가 모든 기능을 충분히 검증했는지 확인하기 위해서 사용된다.
    • Code coverage가 낮으면 테스트되지 않은 코드 영역이 많다. (숨은 버그 가능성이 높다.)
    • Code coverage가 높으면 테스트가 코드 대부분을 실행했음을 의미하여 테스트 신뢰성이 높다.
  • 종류

    Coverage 종류 설명
    Function Coverage 모든 함수가 실행되었는가
    Statement Coverage (Node Coverage) 모든 코드 라인이 실행되었는가
    Branch Coverage (Decision/Edge Coverage) 모든 분기(if 등)의 True/False가 실행되었는가
    Condition Coverage (Predicate Coverage) 각 Boolean 조건이 True/False로 평가되었는가
    Condition/Decision Coverage Condition + Branch Coverage
    Modified Condition/Decision Coverage (MCDC) 각 조건이 결과에 독립적으로 영향을 미치는지 확인
    Multiple Condition Coverage 모든 조건 조합을 테스트

Statement Coverage

  • 프로그램 내 모든 “Statement(문장)”가 최소 한 번은 실행되는지 확인하는 Coverage 기준

Statement 란 -> 코드에서 각 실행 가능한 문장

  • 목적
    • 모든 Statement가 테스트 케이스에 의해 실행되는지 확인
    • Statement Coverage가 낮으면 테스트 되지 않은 코드 영역이 존재함을 의미한다.
  • 특징
    • 테스트 구성이 쉽고 빠르다. (단순히 Statement가 실행만 되면 된다.)
    • 코드 누락 탐지가 가능하다.
      • if-else 같은 조건 분기에서 충분히 테스트를 하지 않을 가능성이 존재한다.
    • 기본적인 시작점이다.
    • 더 높은 수준으로 확장이 필요하다.

Branch Coverage

  • 모든 분기 (Branch), 즉 if-else 조건의 각 방향 (True/ False)이 테스트 케이스에서 적어도 한 번은 실행되는지 확인하는 Coverage 기준
    • Branch란? “조건문(if-else, switch문 등)에서 가능한 실행 경로”
  • 목적
    • 모든 조건의 모든 분기 경로가 테스트되는지 확인한다.
    • 조건이 True, False 인 경우 모두 실행하도록 테스트를 구성한다.
  • 특징
    • Statement Coverage 보다는 더 엄격한 Coverage이다.
    • 조건 논리 오류 검출이 가능하다.
    • 조건문 분기를 모두 테스트가 가능하다. (조건 내에 복잡한 논리 (AND / OR)은 커버하지 못한다.)
    • Branch Coverage를 만족하면 자동적으로 Statement Coverages는 100% 만족한다.

Condition Coverage

  • 복합 조건문 내 개별 Booelan 조건 각각이 True / False로 평가되는지 확인하는 Coverage 기준
    • Branch Coverage의 한계인 조건 내부 세부 조건을 해결 가능
  • 목적
    • 복작한 조건문 내부에서 모든 Boolean 조건이 양 방향으로 평가되는지 확인한다.
    • 조건 내부의 논리 오류(AND / OR)를 더 정밀하게 탐지가 가능하다.
  • 특징
    • 복합 조건문 내부 오류를 검출 가능하다.
      • 전체 if 문 논리 흐름의 검증과는 별개이다.
    • AND / OR 조합 오류 탐지가 가능하다.
    • 조건 간의 상호작용은 탐지가 불가능하다.
    • Condition Coverage가 Branch Coverage보다 더 세밀한 검증을 제공하는 것은 맞지만, 두 개의 Coverage는 서로 독립적이다.
      • 즉 하나가 100%여도 다른 것이 100%가 아닐 수 있다.

Condition / Decision Coverage

  • Branch Coverage (Decision Coverage) + Condition Coverage를 동시에 만족하는 Coverage 기준
  • 전체 조건문의 결과 (True / False)도 모두 테스트 해야 한다.
  • 조건문 내부의 모든 조건이 True / False로 모두 평가되는 것도 테스트 해야 한다.
  • 목적
    • Branch Coverage와 Condition Coverage로 각각의 모든 경우를 실행되는지 확인할 수가 없다.
    • 둘을 동시에 충족해야 더 강력한 논리 오류 탐지가 가능하다.
  • 특징
    • 논리 오류 탐지에 강력하다. (테스트 케이스 수가 많아지기는 한다.)
    • 실무에서 많이 사용된다.

Multiple Condition Coverage

  • 조건문 내 모든 개별 조건들의 가능한 모든 조합을 테스트하는 Coverage 기준
  • 목적
    • Condition Coverage는 각 조건이 True / False로 평가되었는지 확인을 할 수 있지만, 조건들 간의 조합까지는 확인하지 않는다.
    • 조건들 간 모든 조합을 테스트하여 논리적 오류 탐지 가능성을 최대화한다.
  • 특징
    • 조건 간 모든 논리 조합 검증이 가능하기에 가장 강력한 Coverage이다.
    • 논리 오류 탐지율이 최고여서 현실적으로는 어려울 수 있다.

MCDC

  • 각 개별 조건이 전체 조건문의 결과 (Decision)에 독립적으로 영향을 미치는지 확인하는 Coverage 기준

  • 목표

    • 조건문 내의 각 조건이 전체 결과에 영향을 주는지 확인한다.
    • 조건문 전체 결과(True / False)가 특정 조건 하나의 변화만으로 바뀌는 테스트 케이스가 존재해야 한다.
      • 조건마다 독립적인 영향력을 테스트
  • 특징

    • Multiple condition Coverage로는 모든 조건 조합이 테스트가 가능하지만 이는 테스트 케이스가 너무 많은 문제점이 존재한다.

    그보다 훨씬 적은 테스트 케이스로 충분히 강력한 검증을 제공한다.

    • MCDC는 Multiple Condition Coverage(2의 n승 개의 테스트)보다 작은 테스트 케이스를 가진다.
      • n + 1개에서 2의 n승까지 필요로 한다.
    • 실무에서 가장 현실적이고 강력하다.

부록 : Coverage Comparison

Test Coverage