ISO 26262에서는 단위 테스트의 구조 커버리지 지표로 구문 커버리지, 브랜치 커버리지, MC/DC 커버리지를 제시하며, MC/DC는 ASIL A·B·C에서 권고, ASIL D에서 강하게 권고됩니다. 모든 ASIL에서 MC/DC 100%라는 고정 목표값을 직접 강제하는 것은 아니지만, ASIL D 안전 관련 SW에서는 강하게 권고되는 지표이며 미달성된 커버리지에 대해서는 추가 테스트나 충분한 rationale이 요구됩니다. 이런 흐름 속에서 ASIL D 단위 테스트 보고서에 “MC/DC 100%”라는 숫자가 사실상 핵심 지표로 자리잡았습니다.
그런데 한 번 자문해 볼 필요가 있습니다. 보고서에 적힌 그 100%는 무엇을 증명하고 있을까요? 그리고 무엇은 증명하지 못할까요?
도구가 자동으로 보고하는 100%와 실제로 안전을 보장하는 100% 사이에는 적지 않은 간극이 있습니다. 이 간극을 이해하지 못하면, MC/DC 100%라는 숫자는 오히려 그릇된 안심으로 이해되기도 합니다. 이번 뉴스레터에서는 자동차 SW 단위 테스트를 직접 수행하거나 검토하는 분들을 대상으로, MC/DC 커버리지가 실제로 의미하는 것과 도구의 한계를 정리합니다.
1. 커버리지의 위계 - Statement < Branch < MC/DC
같은 “100% 커버리지”라도 어떤 기준이냐에 따라 보장 수준이 완전히 다릅니다. Statement Coverage는 모든 명령문(statement)이 최소 한 번 실행된다는 것을 뜻합니다. Branch Coverage는 모든 분기의 참/거짓 양쪽 경로가 실행됐다는 것을 의미하죠. MC/DC는 결정 안의 각 조건이 독립적으로 결정 결과에 영향을 미치는 케이스가 모두 시연됐다는 것이죠.
예를 들어 if (A && B && C) 같은 결정문이 있을 때, Branch Coverage는 결정 결과가 참인 경우와 거짓인 경우 두 가지만 시연되면 100%입니다. 그러나 MC/DC는 A/B/C 각각이 독립적으로 결과에 영향을 주는 케이스를 모두 시연해야 합니다. 단순 독립 조건식이라면 unique-cause MC/DC 기준으로 N개 조건에 대해 일반적으로 N+1개 정도의 테스트 케이스로 시연이 가능합니다. 다만 조건이 강하게 결합되어 있거나 동일 조건이 반복 등장하는 결정문에서는 더 많은 케이스가 필요하거나 엄밀한 독립성이 성립하지 않을 수 있습니다.
같은 100%지만 Branch와 MC/DC는 잡아내는 결함의 종류가 다릅니다. ISO 26262가 ASIL-D에 MC/DC를 강하게 권고하는 이유는, 안전 로직의 복합 조건에서 일부 조건이 사실상 죽어 있어도 Branch 100%는 그것을 가려준다는 한계 때문입니다.
2. MC/DC가 정확히 무엇을 증명하는가?
MC/DC가 보여주는 것은 한 가지로 요약할 수 있습니다. “해당 테스트 세트 안에서, 이 결정문 안의 각 조건이 결정 결과에 독립적으로 영향을 줄 수 있음이 시연되었다.”
이 보장은 의미가 큽니다. 안전 요구사항이 “조건 A 또는 B가 만족되면 안전 정지를 트리거한다”라고 되어 있을 때, 코드에서 B가 사실상 무시되어도 Branch 100%는 통과할 수 있습니다. MC/DC는 B가 단독으로 결과를 바꾸는 케이스를 강제하므로, 그런 결함을 탐지할 가능성이 높아집니다.
다만 MC/DC가 증명하지 못하는 것을 명확히 해야 합니다. 입력값이 의미 있는 도메인 값인지, 즉 도구는 결정 결과를 바꾸는 입력만 찾으면 됩니다. 그것이 실제 시스템에서 발생할 수 있는 값인지는 보지 않습니다. 결과가 올바른지(테스트 오라클), MC/DC는 코드가 어디까지 실행됐는지를 측정할 뿐, 결과가 정답인지는 별도로 검증해야 합니다. 요구사항이 만족되는지, 코드 커버리지는 요구사항 커버리지와 다릅니다.
3. 도구가 자동으로 채워주는 영역
일반적인 단위 테스트 도구가 MC/DC 측정/자동 생성에서 잘하는 것은 다음과 같습니다.
- 조건 조합 도출 지원: 결정문을 분석해 MC/DC 조건을 만족하는 입력 조합 후보를 계산하거나, 필요한 조합을 식별
- 누락된 조합 식별: 어떤 조건의 독립성 시연이 빠졌는지 보고
- 부분 실행 추적과 시각화: 어느 라인의 어느 조건이 어떤 조합에서 실행되지 않았는지 표시
- 자동 테스트 케이스 골격 생성: 입력값 후보 제시(특히 정수/불리언 도메인)
여기까지는 도구가 매우 효율적으로 처리합니다. 단위 테스트 도구를 도입하지 않은 조직이 MC/DC 100%를 수동으로 달성하려면 비현실적인 공수가 들기 때문에, 도구 활용은 사실상 전제조건입니다.
4. 도구가 일부 지원할 수는 있으나 사람이 책임져야 하는 영역
문제는 그 다음입니다. 다음 네 가지는 도구가 일부 지원할 수는 있어도 최종적으로 사람이 판단하고 근거를 남겨야 하는 영역이며, 이 부분이 비어 있으면 100%는 의미를 잃습니다.
의미 있는 테스트 오라클: 도구가 자동 생성한 테스트 케이스는 종종 “함수가 호출되고 예외 없이 반환되었다”만 검증합니다. 일부 도구가 단언(assertion) 템플릿을 제시하기는 하지만, 결과값이 안전 요구사항에 부합하는지를 검증하는 단언은 결국 사람이 작성해야 합니다. 단언 없는 100%는 “도달은 했으나 검증은 하지 않았다”와 같습니다.
안전 요구사항과의 매핑: ISO 26262 Part 6은 단위 수준 요구사항과 소프트웨어 안전 요구사항을 기반으로 단위 테스트를 수행하도록 요구합니다. ASPICE® SWE.4는 소프트웨어 유닛, 검증 수단, 검증 결과 사이의 일관성과 양방향 추적성을 요구합니다. 코드 라인을 모두 거쳤다는 사실만으로는 어떤 요구사항이 검증되었는지 알 수 없습니다. 요구사항-테스트 케이스 추적 행렬은 사람이 채워야 합니다.
도메인 경계값과 비정상 입력: MC/DC는 결정 결과를 바꾸는 입력 한 쌍이면 충족됩니다. 일부 도구가 경계값 후보를 제시하기도 하지만, 안전 결함은 흔히 경계값(0, MAX, 음수, 오버플로우), 비정상 입력(NaN, 미초기화 메모리), 동시성 조건에서 발생합니다. 이런 케이스의 선정은 안전 분석(FMEA, FTA)을 토대로 사람이 판단해야 합니다.
Stub/Mock의 정합성: 단위 테스트는 의존성을 stub/mock으로 분리합니다. 그 stub이 실제 의존성의 행동을 충분히 모사하는지는 도구가 자동으로 보장하지 않습니다. 잘못된 stub은 “통과하는 테스트와 실패하는 실제 시스템”을 만듭니다.
마무리: 100%를 어떻게 달성했는지가 핵심이다
결국 ISO 26262 평가자나 인증기관이 보고 싶어 하는 것은 “숫자 100%”가 아니라 “100%에 도달한 과정” 입니다. 평가에서 다음과 같은 질문이 나옵니다.
- 테스트 케이스의 입력값은 어떤 근거로 선정되었는가?
- 각 테스트 케이스는 어떤 안전 요구사항을 검증하는가?
- 자동 생성된 테스트와 사람이 작성한 테스트의 비율은 어떠한가?
- 단언(assertion)은 결과의 어떤 측면을 검증하는가?
- 단락 평가/부수효과/stub의 정합성은 어떻게 다루었는가?
이 질문에 답할 수 없는 100%는 평가에서 결국 추가 증적 요구로 돌아옵니다. Automotive SPICE®평가에서도 마찬가지입니다. Automotive SPICE®에서는 단순한 커버리지 숫자가 아니라 위 질문에 대한 답을 요구합니다.
즉 커버리지 100%를 목표로 삼는 것 자체가 문제는 아닙니다. 오히려 구조 커버리지는 테스트의 빈틈을 드러내는 데 여전히 강력한 지표입니다. 다만 그 숫자가 검증의 끝으로 해석될 때 한계가 생깁니다. 필요한 것은 “커버리지 100%를 달성했는가”에서 한 걸음 더 나아가, “그 100%가 어떤 요구사항, 어떤 기능 시나리오, 어떤 인터페이스, 어떤 회귀 위험을 설명하는가”를 함께 관리하는 것도 같이 고민해야, 더 나은 테스트 결과로서 활용할 수 있지 않을까 합니다.