변경 조건/결정 커버리지 테스팅 (Modified Condition/Decision Coverage Testing, MC/DC)

MC/DC는 결정문 내의 각 조건이 독립적으로 결정의 결과에 영향을 미치는지 확인하는 테스트 기법이다.
이는 조건 커버리지와 결정 커버리지를 확장한 개념으로, 복잡한 논리 표현식의 각 입력이 출력에 미치는 영향을 독립적으로 보여준다.

먼저, MC/DC의 기본 개념을 이해하기 쉬운 예제를 통해 살펴보자:

1
2
3
public boolean validateFlight(boolean autopilotEngaged, boolean altitude, boolean airspeed) {
    return autopilotEngaged && (altitude || airspeed);
}

이 코드는 비행 조건을 검증하는 간단한 함수이다. 자동조종장치가 켜져 있고, 고도나 속도 중 하나가 적절한 경우에만 비행이 허용된다.
MC/DC에서는 각 조건이 독립적으로 전체 결과에 영향을 미치는 것을 검증해야 한다.

MC/DC를 만족하기 위한 테스트 케이스를 설계해보자:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@Test
void testFlightValidation() {
    // autopilotEngaged의 영향을 테스트 (다른 조건은 고정)
    assertTrue(validateFlight(true, true, false));   // autopilot이 true일 때
    assertFalse(validateFlight(false, true, false)); // autopilot이 false일 때
    
    // altitude의 영향을 테스트 (autopilot = true로 고정)
    assertTrue(validateFlight(true, true, false));   // altitude가 true일 때
    assertFalse(validateFlight(true, false, false)); // altitude가 false일 때
    
    // airspeed의 영향을 테스트 (autopilot = true, altitude = false로 고정)
    assertTrue(validateFlight(true, false, true));   // airspeed가 true일 때
    assertFalse(validateFlight(true, false, false)); // airspeed가 false일 때
}

이제 더 복잡한 예제를 통해 MC/DC의 중요성을 자세히 살펴보자:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class MedicalAlertSystem {
    public boolean requiresEmergencyResponse(
        boolean highHeartRate,
        boolean lowBloodPressure,
        boolean highTemperature,
        boolean lowOxygenLevel
    ) {
        return (highHeartRate && lowBloodPressure) || 
               (highTemperature && lowOxygenLevel);
    }
}

이 의료 경보 시스템에서 MC/DC를 만족하기 위한 테스트 케이스를 설계해보면:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Test
void testMedicalEmergencySystem() {
    MedicalAlertSystem system = new MedicalAlertSystem();
    
    // 첫 번째 조건부 (highHeartRate && lowBloodPressure) 테스트
    // highHeartRate의 독립적 영향
    assertTrue(system.requiresEmergencyResponse(true, true, false, false));
    assertFalse(system.requiresEmergencyResponse(false, true, false, false));
    
    // lowBloodPressure의 독립적 영향
    assertTrue(system.requiresEmergencyResponse(true, true, false, false));
    assertFalse(system.requiresEmergencyResponse(true, false, false, false));
    
    // 두 번째 조건부 (highTemperature && lowOxygenLevel) 테스트
    // highTemperature의 독립적 영향
    assertTrue(system.requiresEmergencyResponse(false, false, true, true));
    assertFalse(system.requiresEmergencyResponse(false, false, false, true));
    
    // lowOxygenLevel의 독립적 영향
    assertTrue(system.requiresEmergencyResponse(false, false, true, true));
    assertFalse(system.requiresEmergencyResponse(false, false, true, false));
}

MC/DC의 주요 요구사항

  1. 모든 진입점과 출구점이 실행되어야 한다.
  2. 모든 조건이 가능한 모든 결과를 가져야 한다.
  3. 각 조건이 다른 조건과 독립적으로 전체 결정의 결과에 영향을 미쳐야 한다.
  4. 각 결정이 가능한 모든 결과를 가져야 한다.

실제 개발 현장에서 MC/DC를 적용할 때 주의해야 할 점

  1. 단축 평가(Short-circuit evaluation) 고려:

    1
    2
    3
    
    public boolean checkSafety(boolean primarySystem, boolean backupSystem) {
        return primarySystem || (backupSystem && isPowerAvailable());
    }
    

    이 경우, primarySystem이 true일 때는 나머지 조건이 평가되지 않는다는 점을 고려해야 한다.

  2. 중첩된 조건의 처리:

    1
    2
    3
    4
    5
    6
    7
    8
    
    public boolean validateProcess(boolean condition1, boolean condition2) {
        if (condition1) {
            if (condition2) {
                return true;
            }
        }
        return false;
    }
    

    중첩된 조건에서는 각 조건의 독립적 영향을 더 신중하게 검증해야 한다.

주요 특징

  1. 각 조건의 독립적 영향 검증: 결정문 내의 모든 조건이 독립적으로 결과에 영향을 미치는지 확인한다.
  2. 효율적인 테스트 케이스: n개의 조건에 대해 최소 n+1개의 테스트 케이스만으로 100% 커버리지를 달성할 수 있다[1].
  3. 안전 중요 시스템에 적합: 항공, 자동차, 의료 기기 등 안전이 중요한 산업에서 널리 사용된다.

장점

  1. 높은 오류 검출 확률: 복잡한 조건문에서 발생할 수 있는 오류를 효과적으로 찾아낼 수 있다.
  2. 테스트 케이스 수 감소: 다중 조건 커버리지(MCC)에 비해 훨씬 적은 수의 테스트 케이스로 높은 커버리지를 달성할 수 있다.
  3. 안전 중요 시스템의 신뢰성 향상: 철저한 테스트를 통해 소프트웨어의 신뢰성을 높일 수 있다.

한계점

  1. 테스트 케이스 설계의 복잡성: 각 조건의 독립적 영향을 보여주는 테스트 케이스를 설계하는 것이 어려울 수 있다.
  2. 시간과 비용: 완전한 MC/DC 달성을 위해서는 상당한 시간과 리소스가 필요하다.
  3. 도구 지원의 필요성: 복잡한 조건에서 MC/DC 분석을 수행하기 위해서는 자동화된 도구의 지원이 필요할 수 있다.

적용 방법

  1. 모든 결정문 식별: 프로그램 내의 복잡한 불리언 조건을 포함한 모든 결정문을 식별한다.
  2. 테스트 케이스 설계: 각 조건이 독립적으로 결과에 영향을 미치도록 테스트 케이스를 설계한다.
  3. 테스트 실행 및 분석: 설계된 테스트 케이스를 실행하고 결과를 분석하여 각 조건의 독립적 영향을 확인한다.
  4. 커버리지 측정: MC/DC 기준에 따라 커버리지를 측정하고 필요한 경우 추가 테스트를 수행한다.

MC/DC는 복잡한 의사결정 구조를 철저히 테스트하여 숨겨진 결함을 찾아내는 데 효과적인 테스트 기법이다.
특히 안전이 중요한 시스템에서 소프트웨어의 신뢰성을 높이는 데 큰 도움이 된다.


참고 및 출처