엄지월드

4. 테스트 설계 기법 본문

QA

4. 테스트 설계 기법

킨글 2020. 10. 17. 23:18
반응형

4.1. 테스트 설계 및 구현 프로세스(Test design & implementation process)

- 테스트 분석 과정에서 무엇을 테스트할지 결정하기 위해, 즉 테스트 조건(Test Condition)을 식별하기 위해 테스트 베이시스(Test basis)를 분석한다.

- 테스트 조건은 하나 이상의 테스트 케이스로 확인 가능한 항목 또는 이벤트이다. 

- 테스트 조건의 예로는 기능, 트랜잭션(Transaction), 품질 특성 또는 구조적 요소 등이 있다. 

- 테스트 조건과 명세 및 요구사항 사이에 추적성(Traceability)을 유지함으로써, 요구사항이 변경되었을 때의 영향도 분석(Impact analysis)과 테스팅에 의한 요구사항 커버리지(Requirement coverage)를 확인할 수 있게 한다.

- 테스트 설계 및 구현 단계에서 테스트 케이스를 설계하고 작성한 후, 우선순위를 선정하고 배치하여 테스트 프로시저 명세서(Test procedure specification)를 만든다. 

- 테스트 프로시저(또는 수동 테스트 스크립트)는 효율적인 테스트를 위한 테스트 케이스 실행 순서이다. 

- 만약 테스트 실행 도구를 사용하여 테스트를 수행한다면 테스트 프로시저는 테스트 스크립트(또는 자동화된 테스트 프로시저)로 기술할 수 있다. 

- 테스트 케이스의 목적은 목표하는 보장성을 만족하는 최소한의(최적의) 테스트 케이스로 가능한 많은 결함을 발견하는 것이다. 

- 이때 테스트 대상을 가능한 빠짐없이 테스트하여 원하는 수준의 테스트 보장성(Coverage)을 확보할 수 있도록 테스트 케이스를 설계해야 한다. 

- 테스트 케이스는 공식적인 기법이나 경험 기반의 비공식적인 기법을 이용해 도출한다. 
- 테스트 하네스(Test harness)는 테스트 대상이 실행되는 환경을 시뮬레이션함으로써 컴포넌트나 시스템 일부에 대한 테스팅을 가능하게 한다. 이것은 테스팅 환경의 어떤 컴포넌트가 아직 준비가 돼있지 않고 스텁이나 드라이버로 대체된 상태일 때 사용되거나 또는 결함이 테스트 대상 내에서만 국한되도록 예측 및 제어 가능한 테스트 환경을 제공하는 목적으로 사용된다.

- 테스트 드라이버(Driver)는 테스트 중에 시스템 모듈을 호출하는 기능(Functions)이다. 상향식(Buttom-up) 통합 테스트 접근에서 사용된다.

- 테스트 스텁(Stub)은 테스트 중에 모듈에 의해 호출되는 기능이다. 하향식(Top-down) 통합 테스트 접근에서 사용된다.

- 테스트 용이성이 높은 요구사항(Testable requirements)이란 요구사항이 충족됐는지를 결정하기 위해 테스트를 쉽게 설계(Test design)하고 실행(Test execution)할 수 있게 지원한다. 

 

4.2.테스트 설계 기법의 종류 

- 테스트 기법을 블랙박스와 화이트박스로 구분하는 것은 전통적인 방법이다.

- 블랙박스 기법은 명세 기반 기법과 경험 기반 기법을 포함한다.

- 명세 기반 기법의 일반적인 특징

1) 해결할 문제를 명세하기 위해 공식적이거나 비공식적인 모델을 사용한다.

2) 이러한 모델에서 테스트 케이스를 시스템적으로 도출하는 것이 가능하다.

3) 커버리지를 측정할 수 있으나 그 의미가 구조 기반 기법의 커버리지에 비해 제한적이다(상태 전이 커버리지, 결정 테이블 커버리지, 요구사항 커버리지 등)
4) 하위레벨 테스팅 뿐만 아니라 상위레벨 테스팅 등 모든 테스트 레벨에서 사용 가능하다. 

- 경험 기반 기법의 일반적인 특징

1) 테스트 관련 인력의 지식이나 경험으로 테스트 케이스를 도출한다.
ex) 테스터, 개발자, 사용자의 소프트웨어에 대한 지식

ex) 소프트웨어에서 자주 발생하는 결함이나 결함 분포 등의 지식 

- 블랙박스 기법은 테스트 대상의 내부구조(코드)를 참조하지 않고 테스트 베이시스(Test basis) 그리고 개발자와 테스터, 사용자들의 경험을 바탕으로 기능적 혹은 비기능적 테스트 케이스를 도출하고 선택하는 방법이다. 

- 화이트박스 기법(구조 기반 기법)은 컴포넌트(단위) 또는 소프트웨어(시스템)의 구조(코드)를 중심으로 테스트 케이스를 도출하는 방법이다. 

- 구조 기반 기법의 일반적인 특징

1) 코드와 개발 설계 등의 소프트웨어 구현 정보를 기반으로 테스트 케이스를 도출한다. 

2) 수행된 테스트 케이스를 바탕으로 테스트 커버리지를 측정할 수 있으며, 커버리지를 높이기 위해 테스트 케이스를 시스템적으로 도출해 추가할 수 있다. 
3) 구조기밥 기법에서도 입력 및 출력 데이터가 필요한 경우에 등가 분할이나 경계값 분석 등과 같은 입력 값을 선택하는 기법을 사용할 수 있다. (문제)
4) 구조 기반 기법은 소프트웨어나 시스템의 구조(Structure)를 중심으로 테스팅하는 것으로 상위레벨의 명세나 시스템에 구조적인 부분이 있으면 해당 부분의 테스트를 구조 기반 기법으로 설계할 수 있다. (문제) 
5) 구조기반 테스트 설계 기법은 상위레벨 테스팅(High level testing)에 적용될 수 있다. 

- 리스크와 중요도가 높은 기능에 대해서는 코드 구조를 보면서 테스팅하는 제어 흐름 테스팅(Control flow testing) 기법이나 다중 조건 커버리지(Multiple condition coverage)를 달성하는 테스팅 기법을 적용할 수 있다. 

 

4.3. 기본 설계 기법(Fundamental test design techniques)

4.3.1. 명세 기반 기법(Specification-based technique)

- 명세 기반 기법에는 다음과 같은 종류가 있다

1) 동등 분할(Equivalence partitioning)

2) 경계값 분석(Boundary value analysis)

3) 결정 테이블 테스팅(Decision table testing)

4) 상태 전이 테스팅(State transition testing)

5) 유즈케이스 테스팅(Use case testing)

- 명세 기반 기법은 주어진 명세(일반적으로 개발 설계 모델 형태)를 바탕으로 테스트 케이스를 도출하는 것을 의미하며, 해당 테스트 케이스를 실행해 중대한 결함이 없음을 보장한다.

- 요구사항 분석서, 설계(기준)서 등의 명세는 구현하고자 하는 소프트웨어를 최대한 이해하기 쉽고 체계적으로 표현한 것이다. 이를 위해 여러가지 표현 방식(또는 모델)을 활용하는데 최근에는 UML(Unified Modeling Language)을 많이 사용하고 있다. 

- 만약 명세를 구성하는 모델이 UML에서 정의한 상태 다이어그램(State Diagram)이라면, 상태 다이어그램이 소프트웨어를 정확하게 표현하고 있는지, 소프트웨어가 이에 맞게 구현되어 있는지 확인하는 것이 필요하다.

- 이때 상태 전이 테스팅을 적용할 수 있으며 상태 자체를 포함하여 상태가 전이(Transition)되는 것까지 보장하는 테스트 케이스를 생성할 수 있다. 

- 이를 상태 전이 커버리지라 하며 이 외에도 상태 커버리지, 상태 경로 커버리지가 존재한다.

- 상태 전이 커버러지가 상태 커버리지를 포함하고, 상태 경로 커버리지가 상태 전이 커버리지를 포함한다.

(상태 경로 > 상태 전이 > 상태 커버리지)

- 유즈케이스는 UML의 핵심이며 유즈케이스 테스팅은 이러한 유즈케이스를 활용하여 개발한 중간산출물(Work products)을 체계적으로 일정 수준의 보장성을 부여하면서 테스팅한다. 

- 결정 테이블 테스팅 기법도 같은 맥락에서 생각해 볼 수 있다. 개발 산출물을 상태 다이어그램이나 유즈케이스로 작성하지 않고 결정 테이블로 작성했다면 대상 소프트웨어가 결정 테이블로 가장 잘 표현되기 때문일 것이다. 

4.3.1.1 동등 분할(Equivalence partitioning)

소프트웨어나 시스템이 특정 범위의 입력값에 의해 결과값이 동일하다면 이러한 입력값의 범위를 하나의 그룹(클래스)으로 구분할 수 있다. 

- 유한개의 상호 독립적인 집합(Mutual disjoint subset)으로 나누어 수학적인 등가 집합을 만든 후, 각 등가 집합의 원소 중 대푯값을 선택하여 테스트 케이스를 도출하는 것이 동등 분할이다. 

- 동등 분할 클래스는 유효한 입력 데이터뿐 아니라 유효하지 않은 입력 데이터(입력되지 말아야 할 값)도 포함할 수 있다. 입력값 이외에 동등 분할을 적용할 수 있는 항목은 다음과 같다. 
1) 출력값(Outputs)
2) 내부값(Internal values) 
3) 시간 관련 값(Time-related values, 이벤트 이전과 이후)
4) 통합 테스팅에서 다루는 모듈간 인터페이스 파라미터(Interface parameters) 
- 이 기법은 사람에 의한 입력, 인터페이스를 통한 시스템 입력 혹은 통합 테스팅에서 인터페이스 파라미터 등 테스트를 설계할 때 테스트 조건(Test condition)에 등가의 집합으로 표현되는 부분이 있으면 적용할 수 있다. 
- 등가로 분할된 영역을 식별해 테스트 케이스를 설계한다. 이렇게 설계된 테스트 케이스는 같은 특성을 가지면서 같은 방식으로 처리된다고 판단하는 모든 등가 집합(Equivalence classes)에서 대표 입력값을 적어도 하나씩 테스트 했다는 것을 보장한다(이러한 보장성 때문에 동등 분할을 테스트 기법으로 분류하는 것이다). 
- 즉 동등 분할 테스트는 입력과 출력 커버리지를 달성한다. 추가적으로 경험과 필요에 따라 각 등가 집합에서 하나 이상의 값을 선정하여 테스트 케이스를 작성하는 경우, 하나의 대표값을 선정하여 테스팅 하는 것보다 더 많은 결함을 발견할 수는 있지만 동등 분할 커버리지(보장성)는 동일하다.
- 동등 분할은 명세에 있는 입/출력값 등을 활용하기 때문에 명세기반 테스트 기법으로 분류하고 있지만 구조 기반 기법과 경험 기반 기법에서 입/출력 데이터가 필요한 경우에도 해당 기법을 사용할 수 있다. 
- 동등 분할은 모든 테스트 레벨에서 사용 가능하다. 컴포넌트(단위) 테스팅, 통합 테스팅, 시스템 테스팅, 인수 테스팅 각각에서 테스트를 위해 입력값, 출력값, 내부값, 시간 관련 값 등에 동등 분할 기법을 활용할 수 있다.
- 동등 분할은 모든 테스트 유형(Test types)에서도 적용 가능하다. 
- 기능성 테스팅에서는 당연히 적용할 수 있고 비기능성 테스팅, 구조적 테스팅, 확인/리그레션 테스팅에서도 사용할 수 있는 "약방의 감초" 같은 테스트 기법이다. 

4.3.1.2. 경계값 분석(Boundary value analysis) 

- 경계값 분석은 동등 분할의 경계에서 결함이 발견될 확률이 높기 때문에 결함을 예방하기 위해 경계값까지 포함하여 테스트하는 기법이다. 분할영역의 최대값과 최소값은 그 영역의 경계값이 된다. 
- 유효한 분할영역의 경계값은 유효 경계값이 되며, 비유효한 분할영역의 경계값은 비유효 경계값이 된다. 
- 경계값 분석은 동등 분할과 마찬가지로 모든 테스트 레벨, 모든 테스트 유형에 적용할 수 있다. 결함 발견율이 높고 적용하기 쉬운 장점이 있어 가장 많이 사용되는 테스트 기법 중 하나이다.
- 경계값 분석 기법은 종종 동등 분할의 확장으로 여겨지며 동등 분할과 동일한 방식으로 커버리지를 보장한다.
- 동등 분할과 경계값 분석이 사용하기 용이하고 활용도가 높은 기법이기는 하지만 아래와 같은 한계점을 지니고 있다. 
1) 일련의 동작에 대한 조합 테스트에는 적합하지 않다.
2) 입력 범위를 동등 분할하여 제한하더라도 입력값의 조합이 테스트 가능한 수를 넘어서는 경우가 많다. 
3) 입력 조합이 상호간에 독립적(의존성이 없는)이라는 가정에서만 적합한 기법이다.
4) 출력이 입력 조건이나 변수들 사이의 관계에 따라 달라지는 경우, 입력 조건을 동등 분할하는 것이 매우 어려울 수 있다. 

4.3.1.3 결정 테이블 테스팅(Decision table testing)
- 결정 테이블은 논리적인 조건이나 상황(Conditions)을 구현하는 시스템에서 요구사항을 도출하거나 내부 시스템 설계를 문서화하는 매우 유용한 도구이다. 
- 시스템이 구현해야 할 비즈니스 규칙을 문서화하는데 사용된다. 

- 명세를 분석하고 시스템의 조건과 동작을 식별한다. 

- 결정 테이블에서 입력조건과 기대결과는 참과 거짓으로 표현된다. 

- 결정 테이블은 동작을 유발시키는 조건 또는 상황 그리고 각 해당 조합의 예상 결과까지 포함한다. 

- 결정 테이블의 장점
1) 논리적으로 의존적인 가능한 모든 조건들의 조합을 생성함
2) 요구사항 등 테스트 베이시스의 문제점을 발견하는 효과적인 테스트 케이스 생성 가능
3) 테스트 베이시스의 불완전성과 모호함 발견 가능
4) 테스트 케이스를 만들면서 명세의 결함을 발견하는 것이 가능 

- 결정 테이블의 단점

1) 작성에 많은 노력과 시간이 소요 될 수 있음(특히 테스트를 위해 결정 테이블을 만들어야 할 경우 작성 후 개발팀의 검토가 필요함)

2) 복잡한 시스템은 표현하기 어려울 수 있으며 작성 시 논리적 실수 가능성 있음 

4.3.1.4. 상태 전이 테스팅(State transition testing)

- 시스템은 현재 상황(Conditions)과 이전의 이력(History)을 반영하는 상태(States) 및 그 변화(Transition)에 따라 다르게 동작할 수 있다. 

- 상태 전이 다이어그램을 통해 테스트 엔지니어는 소프트웨어 또는 시스템을 상태 사이의 관계 즉, 상태 간의 전이, 상태를 변화시키는 이벤트와 입력값, 상태의 변화로 유발되는 동작 등으로 파악한다. 

- 이때 테스트 대상 시스템이나 객체의 상태는 개별적으로 식별 가능하고 유한한 개수로 표현된다. 

- 여기서 상태 전이 다이어그램을 테이블 형태로 전환한 상태 테이블(또는 상태-이벤트 테이블)은 상태와 이벤트 간의 관계를 보여주고, 개연성은 있지만 요구사항과 맞지 않는 전이(Transition)를 찾아낼 수도 있다

- 상태 전이 테스팅을 통해 다음과 같은 방식으로 테스트를 설계하는 것이 가능하다.
1) 전형적인 상태의 순서를 커버하는 방식
2) 모든 상태를 커버하는 방식
3) 모든 상태 전이를 실행하는 방식
4) 특정한 상태 전이 순서를 실행하는 방식
5) 불가능한 상태 전이를 테스트하는 방식

- 상태 전이 테스팅은 일반적으로 임베디드 소프트웨어 산업분야나 기술적으로 자동화가 필요한 부분에서 사용된다. 

- 특정한 상태를 갖는 비즈니스 객체 모델링이나 인터넷 어플리케이션 또는 비즈니스 시나리와 같이 화면-대화창 흐름을 테스팅할 때도 적절히 적용할 수 있다. 

- 실제로 시스템에서 상태로 표현될 수 있는 부분은 생각보다 많으며 상태로 표현되는 부분은 거의 모든 경우 상태 전이 테스팅 기법 적용이 가능하다. 

- 상태 다이어그램으로 시스템을 설계하는 과정에서 도출할 수 있는 결함을 아래와 같이 모델상의 결함과 구현상의 결함으로 분류할 수 있다.

- 상태 전이 테스팅은 소프트웨어 요구사항을 다이어그램으로 정확하게 표현했다면 상태 전이 커버리지를 갖는 테스트 케이스를 절차에 따라 기계적으로 누락 없이 도출할 수 있다. (문제) 

1) 상태-이벤트 테이블 구성
2) 전이 트리 구성 

3) 반응(Legal, 또는 유효(Vaild)) 테스트 케이스 구성

4) 무반응(Illegal, 또는 비유효(Invalid)) 테스트 케이스 구성

5) 가드(Guard) 또는 조건 테스트 케이스 구성

6) 테스트 프로시저(Test procedure) 구성

- 상태-이벤트 테이블 구성
1) 모든 상태와 이벤트를 빠뜨리지 않고 테이블에 그 관계를 표현한다는 것은 상태 전이 커버리지를 달성하는 모든 '전이'를 테이블의 셀에 나타내는 것을 의미한다. 즉, 해당 이벤트에 의해 해당 상태가 다른 상태로 전이되는 모든 경우를 표현하는 것이다. 

- 전이 트리 구성
1) 달성하는 스위치 커버리지의 수가 높아질수록 테스트가 커버하는 깊이 레벨(depth level)이 높아지므로 더 강도 높은 테스트를 하게 된다. 

- 반응 테스트 케이스 구성

1) 테스트 케이스의 식별 ID는 유일한 것을 부여할 수 있따면 어떤 형태로 표기하여도 상관없다.

- 무반응 테스트 케이스 구성

1) 대기 상태에서 이벤트를 줬을때 아무런 반응을 보이지 않는 것을 구성한다. 

- 가드(Guard) 또는 조건 테스트 케이스 구성 
1) 가드 또는 조건 테스트 케이스는 이벤트가 조건을 포함하고 해당 조건에 따라 기대결과가 달라지는 경우를 반영한 것이다. 

2) 가드의 조건이 동등 분할(집합)을 갖는 조건문으로 구성되어 있으면 도메인 기반 동등 분할(Domain-based Equivalence partitioning) 기법과 경계값 분석(Boundary value analysis) 기법을 적용할 수 있다.

3) 가드가 복잡한 조건문으로 구성되어 있으면 컨디션 커버리지(Condition coverage)를 달성하는 테스트 케이스를 추가 하거나, 해당 부분이 리스크가 높다고 판단되면 MC/DC(Modified condition/decision coverage) 테스팅을 할 수 있다.

- 테스트 프로시저(Test procedure) 또는 스크립트 구성

1) 테스트 프로시저는 테스트의 실행 순서를 나타낸 것으로 테스트 케이스를 순차적으로 나열한 것이다.

2) 테스트 프로시저를 기술한 문서를 테스트 프로시저 명세(테스트 절차 명세)라고 하며, 테스트 스크립트 또는 수동 테스트 스크립트라고도 한다.

- 테스트 케이스 실행의 효율성을 높여 신속하게 테스트를 수행하고자 한다면 테스트 프로시저 명세를 작성하는 것이 필요하다. 

- 테스트 프로시저가 주는 장점은 테스트 실행의 효율성을 높여주는 것 외에도, 테스트 프로시저를 통해 연속된 상태 전이를 이어서 테스트할 수 있으므로 제한적이기는 하지만 테스트 프로시저로 실행된 부분에 대해서는 더 강도 높은 테스트 레벨을 커버할 수 있다. 

- 스위치 커버리지는 리스크에 따라 스위치 깊이 레벨(Switch depth level)을 조절하여 테스팅 해주어야 한다. 
- 리스크가 높은 부분은 높은 스위치 커버리지를 적용해야 하고 상대적으로 낮은 부분은 낮은 스위치 커버리지로도 충분할 수 있다. 

- 리스크와 상관없이 동일한 스위치를 갖는 테스트를 해주거나 심지어는 리스크가 낮은 곳에 높은 스위치 깊이 레벨을 적용하여 테스트를 하는 것은 테스트의 완성도를 낮추는 비효율적인 테스팅의 전형이다. 

- 상태전이 테스팅은 V-모델에서 개발 단계(왼편)에서 진행하는 정적 테스팅을 의미하며 조기 테스트 설계를 하는 한가지 방법이다. 

- 상태전이 테스팅은 시스템이 상태로 표현될 수 있어야 적용이 가능하다.

4.3.1.5. 유즈케이스 테스팅(Use case testing)

- 유즈케이스나 비즈니스 시나리오를 기반으로 테스트를 명세화할 수 있다. 

- 하나의 유즈케이스는 액터(유저 혹은 시스템)와 액터 사이의 상호작용을 표현하고, 해당 상호작용은 시스템 유저에게 결과값을 제공한다. 

- 각각의 유즈케이스는 그 유즈케이스가 성공적으로 수행되기 위한 전제조건(Preconditions)을 가지고 있다. 

- 각각의 유즈케이스는 임무를 완수한 후 후속조건(Post-conditions - 관찰 가능한 결과와 시스템의 마지막 상태)을 가지면서 종료된다. 

- 유즈케이스는 대개 주류 시나리오 또는 기본 흐름과 대체 흐름으로 구성되어 있다. 

- 유즈케이스는 시스템이 실제 사용되는 방식에 기반하여 "프로세스 흐름"을 기술한다. 따라서 유즈케이스에 기반하여 생성된 테스트 케이스는 시스템이 실제 사용되는 프로세스 흐름에서 결함을 발견하는데 상당히 유용하다. 

- 시나리오라고도 불리는 유즈케이스는 고객이나 유저 그룹을 참여시키는 인수 테스트(Acceptance Test)를 설계할 때 매우 유용하다.

- 유즈케이스 테스팅은 통합테스트 단계에서 서로 다른 컴포넌트 사이의 상호작용과 간섭으로 발생하는 통합 결함을 찾는데 도움이 된다(각각의 컴포넌트 테스트는 이러한 결함을 발견하지 못할 수 있음).

- 유즈케이스 테스팅에서는 유즈케이스 각각을 테스팅 하는 방법과 유즈케이스 간의 상호작용과 활동을(시스템 테스팅 레벨에서) 테스팅하는 방법을 생각할 수 있다. 

- 유즈케이스 각각의 테스팅은 유즈케이스 상세(Use case description)에서 흐름과 시나리오만을 고려하여 테스트 케이스를 도출하는 방법과 유즈케이스 상세를 문장별로 분석하여 테스트 케이스를 도출하는 방법이고,

- 유즈케이스 간의 상호작용과 활동을 테스트하는 것은 유즈케이스 간에 수행순서가 있음을 반영하여 활동 다이어그램을 근간으로 테스트 케이스를 도출한다. 

<컴포넌트(단위) 레벨 유즈케이스 테스팅>

- 유즈케이스 상세를 문장별로 분석하여 테스트 케이스를 도출하는 것을 아래의 절차에 따라 진행하면, 누락을 최소화하고 일정 수준의 보장성을 확보할 수 있다. 

1) 어떤 흐름을 테스트 할지 고려하여 테스트 시나리오 구성

2) 유즈케이스 상세에서 테스트에 필수적인 상황 선택

3) 유즈케이스 상세 내용을 입력값(Input), 출력값(Output), 상황 처리(Condition) 등으로 분류하여 테스팅에 관여하는 상황을 선택.

4) 각각의 상황에 ID 부여

5) 각각의 상황에 가능한 값을 설정(Vaild/Invalud, upper/lower bound, true/false, not applicable)

<시스템 레벨 유즈케이스 테스팅>

- 유즈케이스 간의 상호작용과 활동을 테스트

- 활동 다이어그램에 표현된 유즈케이스 활동을 상태(State)의 관점에서 파악하고 활동의 흐름을 전이(Transition)로 간주하여 상태 전이 테스팅 기법의 컨셉을 활용할 수 있다.

- 각각의 활동만을 테스팅하는 활동 기반 커버리지, 활동의 흐름을 테스팅하는 전이 기반 커버리지, 재귀적인 흐름도 고려한 경로 기반 커버리지를 갖는 테스팅이 가능하며 서로 포함 관계가 존재한다. 

- 상태(활동) 커버리지는 앞서 다룬 각각의 유즈케이스 내부를 테스트하는 컴포넌트 레벨의 유즈케이스 테스팅 기법을 이용하여 테스팅할 수 있다.

- 대부분의 유즈케이스가 컴포넌트 테스팅 레벨에서 테스팅 되었다면,
시스템 레벨의 유즈케이스 테스팅에서는 활동 전이 또는 경로 커버리지를 달성하는 테스트를 통해, 유즈케이스 간의 활동전체 시스템 차원에서의 기능적 결함이나 성능상의 결함비기능적 결함을 발견하는 것에 집중한다. 

- 활동 전이 커버리지까지 달성하는 테스트 케이스는 앞에서 상세하게 다룬 상태 전이 테스팅 기법을 적용하여 도출할 수 있다. 

- 유즈케이스 기반 시스템 테스팅에서 경로 커버리지는 활동 다이어그램에 반복(Loop)이 있는 경우, 반복을 모두 고려하여 테스팅하는 것을 의미한다. 

- 유즈케이스로 소프트웨어를 표현하는 것이 다른 공식적인 테스트 기법의 적용 대상이 되는 테스트 베이시스와는 다른 특징이 있어 유즈케이스 테스팅 기법을 적용하는데 적지 않은 어려움이 있을 수 있다. 즉, UML에서는 유즈케이스 이벤트의 흐름을 어떻게 구조화시켜 조직하고 작성해야 하는지를 제시하지 않아 테스트의 근간이 되는 유즈케이스로 표현된 것 자체가 정확하지 않고 일관성이 낮을 수 있다. 

4.3.2. 구조 기반 기법(Structure-based technique)

- 구조 기반(화이트박스) 테스팅은 아래 예시와 같이 소프트웨어나 시스템의 구조(Structure)를 중심으로 테스팅하는 것이다.
1) 컴포넌트 레벨의 구조는 구문(Statement), 결정(Decision) 또는 분기문(Branch)등 코드 그 자체이다. 

2) 통합 레벨의 구조는 한 모듈이 다른 모듈을 호출하는 관계를 도식화한 콜 트리(Call tree) 등이다.

3) 시스템 레벨의 구조는 메뉴 구조, 비즈니스 프로세스 혹은 웹페이지 구조 등이다. 

- 일반적으로 코드의 구조를 테스트하는 기법은 특정 커버리지를 달성하기 위해 테스트를 설계하고 테스트 케이스를 도출하기 위해 사용된다. 

- 명세기반 테스트 기법과는 달리 코드를 기반으로 한 테스트 기법과 커버리지와의 관계는 어느 정도 명확하다. 

예를 들어, 제어 흐름 테스트 기법을 적용한 테스트 케이스에 대해서는 구문 커버리지, 결정 커버리지등을 100% 만족하고, 최소 비교 테스트 기법을 통해 변경 조건/결정 커버리지(MC/DC)를 100% 만족한다. 

1) 구문 커버리지(Statement coverage)는 테스트 스위트에 의해 실행된 구문이 몇 퍼센트인지 측정하는 것으로 다른 커버리지에 비해 가장 약하다. 

2) 결정 커버리지(Decision coverage, branch coverage)는 테스트 스위트에 의해 실행된 결정 포인트 내의 전체조건식이 최소한 참(True)이 한 번 그리고 거짓(False)이 한 번씩 선택되었는지 측정하여 퍼센트로 표현하는 것이다. 개별조건식의 개수와 관계없이 테스트 케이스 최소 개수는 2개로 도출되며 조건, 조건/결정 커버리지에 비해 약하다.

3) 조건 커버리지(Condition coverage)는 전체조건식의 결과와 관계없이 각 개별조건식이 참 한번, 거짓 한번을 모두 갖도록 개별조건식을 조합하는 것으로 결정 커버리지보다 강력한 형태의 커버리지이다. 

4.3.2.1. 구문 테스팅과 커버리지(Statement testing and coverage)

- 컴포넌트 테스팅에서 구문 커버리지는 테스트 스위트에 의해 실행된 구문이 몇 퍼센트인지를 측정하는 것이다. 

- 구문 테스팅은 구문 커버리지를 늘리기 위해 특정 구문을 테스트하는 테스트 케이스를 도출하는 것이다.

- 구문 커버리지는 코드의 모든 구문을 실행할 수 있는 입력값이나 이벤트 등의 테스트 데이터를 제공해 주면 달성 된다.

- 구문 커버리지는 적은 개수의 테스트 데이터로 쉽게 달성할 수 있지만 코드 상에 존재하는 가능한 경우를 모두 검증하지 못하는 보장성이 낮은 커버리지이다.

4.3.2.2. 결정 테스팅과 커버리지(Decision testing and coverage)

- 분기 테스팅과 관련된 결정 커버리지는 테스트 케이스 스위트(Suite, 묶음)에 의해 실행된 조건문 분기(if 구문의 참 혹은 거짓)가 전체 가능한 분기의 몇 퍼센트인지를 측정하고 평가하는 것이다. 

결정 커버리지는 결정 포인트(Decision points) 내의 전체조건식이 "참"과 "거짓"의 모든 값을 갖게 되어 모든 분기로 흐르게 되면 달성된다. 

- 제어 흐름 테스트는 프로그램 구조를 테스트하는 것으로 단위 테스트나 통합 테스트를 수행하기 위해 사용되는 공식적인 화이트박스 테스트 설계 기법이다. 

4.3.2.3. 조건 테스팅과 커버리지(Condition testing and coverage)

- 조건 커버리지는 결정 포인트 내에 있는 개개의 개별조건식이 "참"과 "거짓"의 모든 값을 갖게 되면 달성된다. 

<다중 조건 커버리지(Multiple condition coverage)

- 결정 포인트 내에 있는 모든 개별조건식의 모든 가능한 논리적인 조합을 고려한 강력한 커버리지를 의미한다. 

- 모든 조합의 경우의 수를 고려한 방법이므로 테스트 케이스 양이 매우 방대해지므로 출시 전에 반드시 100% 결함을 제거해야 하는 제품 테스트에서 주로 사용된다. 

- 결정 포인트와 이를 구성하고 있는 모든 개별조건식에서 발생할 수 있는 결함을 찾기 위해서는 최소한 전체조건식의 값이 참과 거짓을 모두 한번씩 가지며, 결정포인트를 구성하고 있는 모든 각 개별 조건식이 참과 거짓 값을 모두 한번씩 갖는 것은 물론, 각 개별조건식은 결정 포인트의 결과값에 독립적인 영향을 주도록 조합을 구성해야 한다. 

4.3.3. 경험 기반 기법(Experience-based technique)

- 경험 기반 테스팅은 이전에 테스터가 다루었떤 유사 어플리케이션이나 기술에서의 경험, 직관, 테스터의 기술 능력으로부터 테스트 케이스를 추출해낸다. 

- 체계적인 기법을 보강하기 위해, 특히 공식적인 기법을 적용한 이후에 추가적으로 경험 기반 기법을 적용하는 것은 공식적인 기법으로 다루기 어려운 특별한 테스트 케이스를 찾아내고 실행하는데 유용하다. 

- 공식적인 테스트 기법과 경험 기반 테스트 기법으로 구현된 테스트 케이스는 찾아낼 수 있는 결함의 종류가 제각기 다르기 때문에 경험기반 테스트 기법이 의미를 갖는다. 

- 테스터의 경험에 따라 효율성 및 효과성의 정도가 매우 달라질 수 있다. 

4.3.3.1. 탐색적 테스팅 접근법

<탐색적 테스팅의 개념>

- 탐색적 테스팅은 애드혹(Ad hoc) 테스팅, Guerrilla 테스팅, Intuitive 테스팅과 유사한 개념의 테스팅이지만, 정해진 Task와 Objectives, Deliverables이 존재한다는 측면에서 다르다. 

- 탐색적 테스팅은 테스트 설계, 수행, 계획, 기록 및 학습을 동시에 진행하는 휴리스틱한 테스팅 접근법이다. 

- 60~120분 동안에 몰입해서 수행할 수 있는 정도의 테스트 목적을 담고 있는 테스트 차터(Test charter)를 기반으로 수행하는 것이 일반적이다. 

- Time-boxing 내에 테스팅의 목적을 정한 후, 몰입하여 최소한의 설명 가능한 Note를 남기면서 테스트를 수행하고
수행 후 Debriefing를 하는 것을 강조한다. (여기에서 어떠한 한가지 구성요소라도 누락되면 차터기반의 탐색적 테스팅이라고 하기 어렵다)

- 탐색적 테스팅은 테스트 설계를 향상시키는 것에 중점을 두고 있는 테스팅 접근법이므로 테스트 설계 기법에 대한 깊이 있는 이해가 없다면 의미 있게 수행하기 어렵다. (테스트 설계를 하지 않는다는 것이 아니고 매우 능숙한 상태에서 머릿속에서 테스트를 설계하자는 것이다.)

- 탐색적 테스팅은 아래와 같은 내용을 포함한다.

1) 제품 탐색(Product Exploration)

2) 테스트 설계(Test Design)

3) 테스트 실행(Test Execution)

4) 직관(Heuristics)

5) 검토 가능한 결과물(Reviewable Results)

- 탐색적 테스팅에서 제안하는 테스트 절차는 아래와 같다.

1) 제품의 목적 식별(Identify the purpose of the product)

2) 기능 식별(Identify functions)

3) 잠재적으로 불안정한 부분 식별(Identify areas of potential instability)

4) 각각의 기능 테스트 및 문제점 기록(Test each function and record problems)

5) 일관성 검증 테스트 설계 및 기록(Design and record a consistency verification test) 

<탐색적 테스팅의 구성요소>

- 테스트 차터를 정할 때에는 먼저 수행할 각 세션당 시간을 정해놓는다(Time boxing) 

- 탐색적 테스팅에서 테스트 매니저의 가장 큰 역할 중 하나가 탐색적 테스팅 수행시 테스터가 테스트에 몰입할 수 있는 여건을 마련해 주는 것이다. 

- 테스터가 제한된 시간 안에 수행해야 할 것은 다음과 같다.

1) 정확한 리포팅(Accurate reporting)

2) 유연성 있는 일정관리(Flexible scheduling)

3) 테스트 방향 정정(Course correction)

4) 견고한 테스팅(Solid testing done)

5) 효율적인 요약 보고(Efficient debriefings)

- 테스트 차터를 효율적/효과적으로 만들기 위해서는 무작정 수를 늘리기보다 제품 리스크에 기반하여 만들어야 한다. 

즉, 리스크 분석 결과 제품의 리스크가 높은 기능에는 테스트 차터를 많이 생성하고, 리스크가 낮은 기능에는 테스트 차터를 적게 생성하여 테스트를 수행하는 것이다. 

- 탐색적 테스팅에서는 문서를 최소화해야 한다고 주장하지만, 테스트 산출물이 전혀 없는 것은 아니다. 

- 메모에 정해진 형식은 없으며 테스터의 사고 추이 및 수행과정을 잘 알아볼 수 있도록 기록하면 된다. 이렇게 작성된 테스트 노트는 테스트 케이스의 역할을 대체함과 동시에, 검토 가능한 결과물로써 활용된다. 
예를 들면, 테스트 프로젝트 감사(Audit)중 테스트 노트를 증거자료로 제시할 수 있다.
- 테스트 노트에 포함되어야 할 내용은 아래와 같다

1) 테스트한 제품에 대한 노트 및 기록

2) 발견한 결함과 장애에 대한 노트 및 기록

3) 어떻게 테스트하였는지를 기술하는 요약된 문서 

- 탐색적 테스팅의 한 세션이 종료된 후에는, 팀원끼리 요약 보고(Debriefing)하는 시간을 갖는다. 

요약 보고 중에는 테스트 중 발견했던 결함과 이슈사항에 대해 보고하고, 어떤 식으로 테스트를 수행했는지에 관한 경험을 팀원 모두가 공유한다. 

- 리스크가 가장 높은 곳에서는 테스팅 경험이 가장 많고 능력 있는 테스트 엔지니어가 탐색적 테스팅을 수행해야 하고,

반대로 리스크가 가장 낮은 곳에는 경험과 능력이 상대적으로 부족한 테스트 엔지니어가 수행해야 한다. 

- 탐색적 테스팅을 성공적으로 수행하게 되면 다음과 같은 효과를 가져올 수 있다

1) 경험적 테스팅을 체계화 시킬 수 있다.
2) 테스트 케이스를 작성하는 시간을 줄여 보다 많은 테스트를 실행할 수 있다.

3) 테스터 또는 테스트 엔지니어의 역량을 월등히 향상시킬 수 있다.

4) 적은 테스트 인력으로 많은 테스트를 수행할 수 있다.

5) 명세가 거의 없고 시간이 부족한 경우 테스트를 효과적/효율적으로 수행할 수 있다. 

4.4. 고급 설계 기법(Advanced test design techniques)

4.4.1. 명세 기반 기법(Specification-based technique)

4.4.1.1. 분류 트리 기법(Classification Tree Method - CTM)

- 분류 트리 기법의 장점을 살펴보면 아래와 같다

1) 테스트 아이디어를 트리 구조로 시각화하여 테스트 케이스를 설계하므로 의도한대로 테스트 케이스를 도출할 수 있다.

2) 시각적으로 보면서 트리 구조 끝단의 조합을 통해 테스트 케이스를 작성하므로 일부분만 테스트를 진행한다거나 중복된 테스트 수행을 피할 수 있다.

3) 복잡한 시스템 혹은 어플리케이션의 일부 또는 전체를 테스팅하는데 적합하다.

4) 개발 설계를 체크하는 용도로 사용이 가능하여, 조기 테스트 설계에 활용할 수 있다.

5) 테스트 케이스 개수와 트리의 복잡도를 근거로 테스트 비용을 추정하는 것이 가능하다. 

4.4.1.2. 페어와이즈 조합 테스팅(Pairwise testing)

- 커버해야 할 기능적 범위에 비해 상대적으로 적은 량의 테스트세트를 구성하여 소프트웨어의 결함을 찾고 테스트에 대한 자신감을 얻을 수 있는 방법중의 한 가지이다.

4.4.1.3. 직교 배열 테스팅(Orthogonal array testing)

- 현재 6Sigma를 포함하는 산업 공학 분야의 실험 계획 및 분석 도구로서 널리 사용되고 있다.

이러한 직교 배열의 원리를 소프트웨어 테스트 설계에 적용하여 조합의 수를 줄임으로써 테스트 케이스의 수를 합리적으로 줄일 수 있다. 

4.4.2. 구조 기반 기법(Structure-based technique)

4.4.2.1. 분할(Splitting) 방법으로 접근한 조건/결정 커버리지

1) 분할(Splitting) : 논리적 테스트 컬럼의 각각을 선택한 커버리지로 생성한 모든 논리적 조합으로 분할(Split)하여 테스트 케이스를 작성하는 방식이다. 모든 조합을 분할해서 나열하기 때문에 결함 원인은 매우 빨리 발견될 수 있지만 테스트 케이스 수가 크게 증가한다. 

2) 포함(Including) : 논리적 테스트 컬럼의 각각을 선택한 커버리지로 생성한 조합 중에서 단 하나만 선택하여 하나의 논리적 테스트 케이스로 작성하는 1:1 전환 방식이다. 따라서 하나의 테스트 케이스에서 개별조건식은 다른 결정 포인트의 결과값과 독립적으로 확인할 수 없으므로 결함의 원인을 항상 즉각적으로 판단(Clear)하기 어렵지만 어느 정도 커버리지를 만족하면서 테스트 케이스 수를 줄일 수 있는 방법이다. 

4.4.3. 경험 기반 기법(Experience-based technique)

4.4.3.1. 오류 추정

- 일반적으로 많이 사용되는 경험 기반 기법은 오류 추정(Error guessing)이다. 대체로 테스터는 경험에 기반하여 결함을 예측한다. 

- 오류 추정 기법은 테스터가 테스트 대상 시스템을 완전히 이해하고 있다는 전제로 하며 식별된 취약점에 기반한 테스트이다. 따라서 테스트의 마지막 단계에서 사용하는 것이 적절하다.

- 오류 추정 기법을 구조적으로 적용하려면 가능한 오류(Errors)를 모두 나열하고 이런 유형의 결함 또는 오류를 공격할 수 있도록 테스트를 설계해야 한다. 이러한 체계적인 접근법을 결점 공격(Fault attack)이라고 부른다.

- 결함이나 장애 리스트는 경험, 형식에 맞지 않거나 결함을 발생시키는 데이터와 장애 데이터, 소프트웨어가 왜 장애를 일으켰는지에 대한 일반적인 지식 등을 근거로 만든다.

- 오류 추정 기법을 통해 언급된 경험 기반 테스팅 기법의 일반적인 유용성을 정리해 보면 아래와 같다.

1) 테스트에 참고할 명세가 거의 없거나 불충분할 경우, 시간적인 압박이 심한 경우 유용하다.

2) 다른 기법이나 공식적인 테스트를 보완할 때 유용하게 사용할 수 있다.

3) 가장 심각한 결함을 찾았다는 확신이 필요한 경우 사용함으로써 테스트 프로세스 및 완성도를 확인하는 기준을 제공할 수 있다. 

- 경험 기반 테스팅에는 오류 추정 기법 이외에도 Exploratory testing, Characteristics testing 등 다양한 형태의 기법이나 접근법이 있으며, 특히 탐색적 테스팅은 실무에서 활용이 많아지면서 사용 범위가 확대되고 있다. 

4.4.3.2. 체크리스트(Checklists)

- 체크리스트는 체계적으로 도출되기 보다는 테스트 경험과 노하우를 정리하고 목록화하여 다음 테스팅에서 해당 내용을 누락 없이 검증하는 것을 목적으로 작성한다.

- 주로 테스팅 절차와 테스트 대상 기능 및 시스템 요소 등을 체크리스트로 작성하며, 일반적으로 체크리스트를 아래와 같이 분류하기도 한다.

1) 일반 체크리스트 : 수행해야 할 테스트 목록과 절차를 나열함

2) 기능 (블랙박스) 체크리스트 
2- 전체 시스템의 최상위 기능 체크

2- 개별적인 컴포넌트(단위) 기능

2- 서로 다른 레벨(컴포넌트, 통합, 시스템 레벨 등)의 기능과 그룹핑 

3) 시스템 요소 체크리스트

3- 상위레벨 서브-시스템이나 모듈

3- 개별 구문이나 데이터 아이템

3- 서로 다른 레벨의 시스템 요소와 그룹핑

4.5. 테스트 기법 선택

- 어떤 테스트 기법을 사용할지 결정하는데 고려해야 할 사항은 아래와 같다.

1) 시스템 유형 및 특징

2) 강제적 표준 또는 법적 기준 적용 여부

3) 고객 또는 계약상의 요구 사항

4) 리스크 수준(Level of risk)

5) 리스크 유형(Type of risk)

6) 테스트 목표

7) 문서(테스트 베이시스)의 존재 유무 

8) 테스터의 지식 수준

9) 시간과 예산

10) 테스트 레벨

11) 개발 수명 주기

12) 유즈케이스, 상태 다이어그램 등 개발 설계 모델 존재 유무

13) 발견된 결함 유형 등 이전의 경험

- 일반적으로 여러 가지 테스트 기법을 동시에 복합적으로 선택해 사용한다.

- 몇몇 특정 기법은 특정 상황과 테스트 레벨에 더 적잡할 수 있으나, 대부분의 기법은 모든 테스트 레벨에 적용할 수 있다. 

4.6. 소프트웨어 특성에 따른 테스팅

- 국제 표준인 ISO/IEC 품질모델에서 제시하는 품질 특성을 기준으로 테스트 케이스를 도출하는 것도 유용하게 테스트를 설계할 수 있는 방법 중 하나이다. 이러한 테스팅 방법을 여기서는 Characteristics testing이라고 칭하도록 한다.

- 특성 테스팅은 테스트 접근법 중 하나인 방법론적 접근법에 속하며, ISO/IEC 9126-2에 명기된 품질 특성을 테스트 케이스 도출 기준으로 사용한다.

- 특성 테스팅은 Functional testing도 포함하지만 Non-Functional testing도 포함한다.

- ISO/IEC 9126에서 기능성 이외의 품질 특성 즉 신뢰성, 사용성, 효율성, 유지보수성, 이식성 등은 비기능성이다. 그러므로 특성 테스팅은 비기능 테스팅을 가이드 하는데 유용하게 활용될 수 있다.

- 기능성은 요구되는 기능 및 성능을 만족시키는 능력을 의미하며, 제품에 대한 기술 문서 즉 제품 기능 정의서와 사용자 요구 문서 등에 언급된 모든 기능을 테스트 케이스로 작성한다.

- 기능성 품질 특성의 품질 부특성을 참고하면 테스트 케이스 도출이 훨씬 용이해진다.

- 각가그이 품질 부특성은 일명 Metric으로 불리는 측정 요소들로 구성되어 있는데, 메트릭을 활용해 테스트 케이스 도출에 도움을 받을 수 있다. 그리고 Metric을 이용해 테스트 결과를 수치화할 수 있다. 

 

 

 

 

 

 

 

 

 

'QA' 카테고리의 다른 글

Test 용어 정리  (0) 2021.03.07
5. 테스트 관리  (0) 2020.11.14
[ISTQB] 외워야 할 부분  (0) 2020.11.10
정적 기법  (0) 2020.10.15
소프트웨어 수명주기와 테스팅  (0) 2020.10.11
Comments