모델기반 테스트를 통한 S/W 초기 검증 


출처 : 임베디드 소프트웨어
글 윤상호, Senior Application Engineer, MathWorks
·약력: 2001년 자동차 분야 제어 시스템 엔지니어로서 연구원 생활을 시작하였으며, 2006년 MathWorks에 입사하여 현재까지 시스템 모델링, 검증 및 코드 생성 전문가로 활동하고 있다. 

11080571.jpg

임베디드 소프트웨어는 너무나 자연스럽게 우리의 생활 속에 스며들어 있다. 휴대폰, TV, 에어컨, 세탁기, 청소기 등과 같은 가전기기뿐만 아니라 자동차, 항공기, 열차, 조선, 의료기기 등과 같은 우리의 생활 속에 필수적인 부분에서 임베디드 소프트웨어의 활용 범위는 다양하다. 현재에는 한 대의 자동차에도 수십/ 수백 가지의 임베디드 S/W를 활용한 제어장치들이 장착되어 있으니 임베디드 소프트웨어의 복잡성과 중요성이 어느 정도일지 쉽게 짐작할 수 있을 것이다. 특히 항공기, 열차, 자동차, 의료기기 등에 장착된 자동 제어 장치 등은 오동작 시 인명 피해를 미칠 수 있는 높은 신뢰성이 필수로 여겨지는 시스템들이며, 이러한 시스템 내의 임베디드 소프트웨어는 개발 과정에서 철저한 검증 절차들이 요구된다.
개발 과정에서 요구되는 소프트웨어들의 안정성을 위해 분야별 개발 프로세스의 표준들이 제정되었으며, 이러한 표준들은 철저한 검증과 테스트 절차들을 요구하고 있다. 가장 대표적인 표준은 IEC 61508이며 E/E시스템(Electrical and Electronic Systems)의 기능 안정성을 위한 일반적인 접근 방법에 대한 내용을 담고 있다. 그 외에도 IEC 61508 표준을 기반으로 하여 산업 분야별로 다양한 표준들이 파생되었으며 그림 1은 파생된 표준들의 예를 보여주고 있다. (그림 1에는 표현되지 않았으나 항공분야의 안정성 관련 표준으로서는 DO-178B나 DO-254 등이 있다.) 


안정성 필수 시스템의 소프트웨어 개발 프로세스 
및 모델 기반 설계

11080572.jpg

안정성 필수 시스템의 임베디드 소프트웨어는 철저한 검증 절차가 요구됨에 따라 개발 프로세스 모델로서 V-모델을 주로 사용한다. 그림 2는 자동차 분야 표준으로서 2011년 말쯤에 제정될 것으로 예상되는 ISO 26262 표준에서 다루는 소프트웨어 개발 프로세스 모델이다.
임베디드 소프트웨어의 개발 프로세스는 요구사항으로부터 설계, 구현, 그리고 테스트를 통한 검증으로 이루어진다. 실제로 개발 초기 단계인 요구사항을 구체화하는 과정이나 설계 과정에서 발생된 결함은 구현 단계를 거쳐 테스트하는 단계에서 주로 발견이 되며, 이러한 설계 오류로 기인한 비용은 설계 초기 단계에서 해결하는 것에 비해 일반적으로 수십 배에 달한다는 분석 결과가 있다. 그림 3은 2004년 NASA에서 분석한 자료로서 결함이 존재한 단계와 결함이 발견된 단계에 따르는 결함 수정 요구비용을 도식화한 것이다. 이에 따라 최근 소프트웨어 공학 분야에서는 요구사항의 단계에서부터 철저한 검증을 통해 잠정적인 소프트웨어의 결함을 초기에 막을수 있는 방법에 대한 연구가 활발하게 이루어지고 있으며, 그 중 대표적인 것이 바로 모델 기반 설계 기법이다. 즉, 설계 과정에서 시뮬레이션을 통한 검증을 수행함으로써 모델링을 통해 요구사항을 보다 정형적으로 테스트해, 검증을 구현 전으로 앞당기는 것이다.

11080573.jpg

그럼 여기서 기능 안전 표준에서 요구하는 다양한 동적 및 정적 테스팅에 대한 부분을 구현 전에 어떻게 해결해야 할 지에 대한 의문이 들 것이다. 이에 대해 다음 절에서 상세히 알아보도록 하겠다.

모델 기반 테스트
실시간 제어 시스템의 개발 시 실제 제어 대상(플랜트)의 특성이 함께 고려되어야 하며 제어 알고리즘은 이러한 제어 대상에 맞게 설계되고 소프트웨어로써 구현이 이루어져야 한다. 즉, 시스템의 모델링은 제어 소프트웨어뿐만 아니라 제어 대상의 특성이 함께 고려되어야 하며, 이에 맞는 알고리즘이 설계되고 소프트웨어로써 구현된다. 
MathWorks의 Simulink 및 Stateflow는 제어 알고리즘과 제어 대상을 함께 모델링하고 시뮬레이션 할 수 있는 환경을 제공한다. 특히, 제어 알고리즘이나 로직에 대해서는 다양한 테스트 케이스들을 모델에 반영하여 표준의 요구사항에 대응가능한 테스트를 수행할 수 있는 환경이 제공된다. 그럼 모델 기반 테스트 방법에 대해 블랙박스 테스트, 화이트박스 테스트, 그레이박스 테스트로 구분하여 상세히 알아보도록 하겠다. 

블랙박스 테스트

11080574.jpg

11080575.jpg

11080576.jpg

블랙박스 테스트는 구현하려는 알고리즘의 기능적 테스트를 위하여 수행된다. 결국, 설계된 알고리즘이 테스트 입력에 대해 요구되는 출력을 내는지에 대해 검증하는 것이다. Simulink에서는 개발하려는 알고리즘 모델과 분리된 테스트 하네스 모델을 따로 구성할 수 있으며, 이러한 테스트 하네스 모델 내에 다양한 테스트 케이스들을 포함하는 구성이 가능하다. 그림 4는 자동차의 자동 변속기 알고리즘을 예로 들어 테스트 하네스 모델을 구성한 예이며, 그 하네스 모델에 포함된 테스트 입력과 출력을 체크하기 위한 Assertion의 구성을 보여준다. 또한, 그림 5는 그림 4의 테스트 하네스 모델에 포함된 입력 테스트 케이스들의 예이다.  
자동차 자동 변속기의 예는 센서를 통해 감지된 차량의 속도와 스로틀의 열리는 정도를 입력받아 최적의 기어 값을 출력으로 만들어주는 알고리즘이다. 상세한 알고리즘 모델은 Simulink와 Stateflow로 구성할 수 있으며, 그림 6은 그 예를 보여주고 있다. 그림 5에서 보는 바와 같이 입력 테스트 케이스들은 예상되는 알고리즘의 출력을 포함하고 있으며 Passing Maneuver, Gradual Acceleration, Hard Braking, Full Throttle과 같은 드라이빙 모드에 대한 각각의 테스트 케이스들을 포함하고 있다. 
Simulink는 이러한 다양한 테스트 케이스들을 한 블록으로 모델링하고, 한번의 클릭으로 모든 테스트를 자동으로 수행할 수 있다. 이 때 설계된 알고리즘의 시간에 따른 출력을 언제나 Scope를 통해 확인할 수 있으며, 예상되는 결과와의 차이가 발생하는 경우 Assertion을 통해 리포트 해 주는 기능을 활용할 수 있다. 

화이트박스 테스트

11080582.jpg

11080577.jpg

블랙박스 테스트를 통한 알고리즘의 기능적 테스트와 함께 Simulink는 Simulink Verification and Validation이란 도구를 통해 기능 테스트를 위해 만들어진 테스트 케이스들이 얼만큼 설계된 알고리즘에 대한 테스트를 커버하는가에 대한 커버리지 분석을 모델 레벨에서 수행하는 기능을 제공한다.
Simulink를 통한 커버리지의 분석에서는 앞서 수행한 블랙박스 테스트에 추가적인 작업 없이도 블랙박스 테스트와 함께 자동으로 수행된다. 분석 가능한 커버리지들은 기능 안전 표준들에서 요구하는 Condition Coverage, Decision Coverage, 및 MC/DC(Modified Condition and Decision Coverage) 등과 함께 Simulink 모델 기반에 맞춰 Signal Range, Signal Size 및 Look-up table Coverage들의 분석도 함께 수행될 수 있다.
그림 6은 자동차 분야 기능 안전 표준인 ISO 26262에서 ASIL(Automotive Safety Integrity Level)에 따라 요구되는 커버리지에 대한 참조 표이며, 그림 7은 Simulink에서 시뮬레이션과 함께 생성된 리포트의 예이다. 생성된 리포트는 하이퍼링크를 통해 커버되지 않은 알고리즘 모델로의 추적이 가능하게 되어 있어 추가적인 테스트 케이스를 확보하는 작업을 도울 수 있다. 

그레이박스 테스트

11080578.jpg

앞의 화이트박스 테스트에 의해 얻어진 커버리지 리포트로 테스트의 커버리지를 개선하기 위한 추가적인 테스트 케이스를 만드는 것 또한 사실 쉬운 일은 아니다. 알고리즘이 복잡하면 할수록 더욱더 어려운 작업이다. Simulink Design Verifier는 Simulink 모델에 대한 동적인 시뮬레이션 수행 과정 없이 모델을 수학적으로 분석(정적 분석)하여 기능 테스트에 활용된 테스트케이스들이 커버하지 못하는 추가적인 테스트 케이스를 생성시킬 수 있다. 또한 생성된 테스트 케이스를 활용해 알고리즘의 기능적 문제점을 초기에 발견하는 것을 돕는다. 그림 8은 Simulink Design Verifier에 의해 MC/DC 커버리지를 100% 만족시키는 테스트 케이스가 생성된 예를 보여준다. 

 자동 코드 생성과 생성 코드의 검증
모델 기반 설계 프로세스에서는 앞에서 언급한 바와 같이 요구사항 명세 및 설계 단계에서 모델을 활용하며, 모델 레벨에서 다양한 테스트를 통해 구현 전 검증 작업을 수행한다. 이로써 뒤늦게 발견될 설계 결함을 개발 초기에 제거함으로 큰 비용 절감의 효과를 가져온다. 더 나아가 Simulink로 설계되고 시뮬레이션을 통해 테스트된 모델은 임베디드 소프트웨어로 구현하기 위해 C/C++ 코드로 자동 생성이 가능하다. 이 때, MathWorks 제품들은 생성된 코드를 검증하기 위한 다양한 솔루션들을 제공한다. (기존에 존재하는 레거시 코드들의 검증도 함께 적용이 가능하다.) 여기서는 이러한 코드 검증을 위한 솔루션에 대해 정적 테스트와 동적 테스트로 구분하여 설명해 보고자 한다. 

정적 테스트

11080579.jpg
코드의 정적 테스트라 함은 코드를 실행하지 않고 코드 자체의 오류를 검출해내는 테스트 방법을 말한다. 
MathWorks사의 Polyspace라는 도구는 Abstract Intepretation이라는 정형기법으로 코드에 신뢰도를 측정할 수 있도록 해준다. 즉, 런타임 에러를 찾는 것에서 더 나아가 런타임 에러가 존재 하지 음을 증명함으로써 산술적 수치로 코드의 신뢰 정도를 알 수 있도록 해준다. 여기서 런타임 에러는 0으로 나누기, 오버플로우와 같은 산술적인 코딩에러, 포인터와 배열의 잘못된 사용, 초기화 하지 않은 데이터의 사용 등과 같은 찾기 어려운 다양한 코딩 상의 에러들을 말한다. Polyspace는 코딩의 오류를 줄이기 위해 활용되는 MISRA-C와 같은 코딩 표준 가이드라인을 준수하는지 확인하는 기능도 포함하고 있다. 
그림 9는 Polyspace를 이용하여 코드를 분석한 결과를 보여 주는 화면으로 코드 상에 Green색으로 보이는 부분이 런타임 에러가 존재하지 않음을 나타내며, 코드가 93.2%의 신뢰도를 갖는다는 것을 보여준다. 

동적 테스트
MathWorks의 코드 생성 도구는 임베디드 프로세서에 최적화된 코드를 생성하기 위해 다양한 최적화 기능으로 생성된 코드를 검증하기 위한 솔루션을 제공한다. 
Software-In-The-Loop(SIL) 테스트와 Processor-In-The-Loop(PIL) 테스트가 바로 그것이다.

11080580.jpg 

Software-In-The-Loop(SIL) 테스트│SIL이라 부르는 Software-In-The-Loop 테스트는 타깃 프로세서에 소프트웨어를 배치하기 전에 구현된 코드가 설계된 것과 동일하게 동작하는지 확인하기 위한 테스트이다. 결국 모델 기반 설계에서의 SIL 테스트는 모델과 모델로부터 생성된 코드가 동일하게 동작하는지를 확인하는 테스트라고 할 수 있다. 
MathWorks의 코드생성 도구는 코드 생성과 동시에 생성된 코드를 모델과 함께 동작 시킬 수 있는 환경을 자동으로 구성한다. 즉, 모델 레벨에서 사용한 테스트 케이스들을 활용하여 코드에 대한 테스트를 수행할 수 있는 환경을 자동으로 만들어 줌으로써 생성된 코드의 검증을 용이하게 한다. (이때, 이미 구현된 레거시 코드도 Simulink 환경으로 가져와 함께 테스트를 수행할 수도 있다.) 또한, 코드 커버리지 분석을 위해 외부 코드 커버리지 분석 도구(Bullseye Coverage, LDRA 등)와의 연동 기능이 함께 제공된다.

11080581.jpg 

Processor-In-The-Loop(PIL) 테스트│Processor-In-The-Loop(PIL) 테스트는 Software-In-The-Loop 테스트와 유사하다고도 볼 수 있으나, 생성된 코드를 타깃 임베디드 프로세서에 넣어 테스트한다는 큰 차이점이 있다. 여기서 타깃 임베디드 프로세서에서 동작시키는 것의 중요한 의미는 Cross-Compiler로 컴파일 된 목적 코드를 프로세서와 함께 테스트한다는 것이다. 
임베디드 소프트웨어 코드를 컴파일하고 다운로드하기 위해 다양한 개발 환경인 IDE들(TI Code Composer Studio, Green Hills MULTI, Analog Devices VisualDSP++, Altium Tasking, Eclipse 등)이 활용되고 있으며, MathWorks의 코드 생성 도구인 Embedded Coder는 이러한 IDE들과의 연동 기능을 제공한다. 코드를 생성시키고 난 후, 자동으로 IDE를 동작시켜 생성된 코드의 컴파일과 다운로드 작업을 한번에 수행할 수 있다. 이 과정에서 코드 생성도구의 옵션에 의해서 프로세서와 Simulink간 데이터를 주고 받을 수 있는 환경을 자동으로 구성할 수 있으며, 이러한 데이터 통신을 통하여 모델로부터 테스트 입력들을 프로세서로 전송하고 프로세서 내에서 동작한 결과를 모델로 전송 받아 분석한다. 이것이 Simulink와 코드 생성 도구가 제공하는 PIL 테스트 환경이다. 결국, 모델의 테스트를 위해 사용된 테스트 케이스들이 또다시 프로세서 내의 소프트웨어 동작 테스트를 위해 사용될 수 있으며, 이는 개발 효율성 측면에서 매우 큰 효과를 가져온다. PIL 테스트를 마치면, 최종적으로 동일한 테스트 입력에 대해 모델 테스트의 결과와 프로세서 내 소프트웨어 동작의 결과가 동일한지를 비교 검증한다. 

결론
임베디드 소프트웨어 개발을 위한 방법으로써 모델 기반 설계 기법은 개발 초기 단계에서의 설계 검증을 가능케 하며, 매우 큰 개발 비용 절감 효과를 가져 올 수 있다. 
MathWorks의 Simulink는 모델 레벨에서 블랙박스 테스트, 화이트박스 테스트 및 그레이박스 테스트를 수행할 수 있는 다양한 기능을 제공하며, 임베디드 소프트웨어로의 구현을 위해 자동으로 C/C++ 코드를 생성시킬 수 있다. 또한 생성된 코드와 기존의 레거시 코드를 검증하기 위해 정적 테스트 및 동적 테스트를 수행할 수 있다. 
MathWorks의 Polyspace는 Abstract Interpretation이라는 정형 기법을 통해 런타임 에러를 정적으로 분석하고 찾아낸다. 동적 테스트를 위해서는 Software-In-The-Loop 테스트와 Processor-In-The-Loop 테스트를 수행할 수 있으며, 각각은 소스 코드의 테스트와 컴파일 된 목적 코드 테스트의 의미를 갖는다.
두 가지 방법 모두 모델 레벨 테스트를 위해 구성한 테스트 환경을 코드 검증을 위해 활용할 수 있다. MathWorks의 코드 생성 도구인 Embedded Coder는 자동 코드 생성 기능에 추가하여 코드의 동적 테스트를 위한 환경을 자동으로 생성시키는 기능을 제공한다.