Ch08. 소프트웨어 테스팅

728x90

Ch08. 소프트웨어 테스팅

📌 [교재] 소프트웨어 공학 10판

[프로그램 테스팅] Program testing

[테스팅 2가지 목적]

  • 검증 테스팅: 프로그램이 의도대로 수행되는지 보여줌
  • 결함 테스팅 : 프로그램 사용 전 결함 발견

[프로그램 테스팅]

  • 인위적인 데이터 이용하여 프로그램 실행시키고 실행 결과 점검

테스팅은 오류 존재 밝힐 수 있지만 오류가 없음을 보일 수 없음

[검증 테스팅] : validation testing

  • 소프트웨어가 고객 요구사항에 맞는지 보여줌
  • 요구사항마다 적어도 하나의 테스트 있어야 하며 시스템이 정확하게 수행되는 것 기대

[결함 테스팅] : defect testing

  • 소프트웨어 결함에 의해 제대로 동작하지 않는 경우를 발견함
  • 테스트 케이스(test case)는 결함 드러낼 수 있도록 설계

[V&V 기술] : Verification & validation

▶소프트웨어 검증 및 확인(V&V) 프로세스

▶확인(validation)

  • 올바른 제품 만들고 있는가?
  • 소프트웨어가 고객 기대에 맞는지 보여줌
  • 명세 따르는 것을 넘어 고객의 요구(기대)하는 것을 제공하는지 확인하는 과정

▶검증(verification)

  • 제품 올바르게 만들고 있는가?
  • 소프트웨어가 기능적/비기능적 요구사항 명세에 맞는지 점검

[소프트웨어 인스펙션과 테스팅]

▶[소프트웨어 인스펙션]

  • 요구사항/설계/소스코드 분석하고 검사하여 문제 찾음
  • 프로그램 실행시키지 않는 정적(Static) V&V 기술
  • 주로 소스코드를 대상으로 하지만 소프트웨어의 어떤 표현이라도 검사 가능

▶[소프트웨어 테스팅]

  • 프로그램 실행시켜 동작을 관찰하는 동적(dynamic) V&V 기술

▶[인스펙션의 장점]

  • 테스팅 중에는 오류가 다르 오류들을 가릴 수 있다.
  • 인스펙션은 정적 프로세스이므로 오류 간 상호작용과는 무관
  • 인스펙션은 한 번에 여러 오류 발견 가능
  • 시스템의 불완전한 버전 검사 가능
  • 불완전 프로그램 테스트용 추가 코드 필요
  • 인스펙션은 결함 찾는 것 뿐 아니라 표준 준수, 이식성, 유지보수성 등의 품질 속성도 검토

▶인스펙션과 테스팅은 상호보완적

  • 인스펙션이 결함 발견하는 건 테스팅보다 효과적
  • 인스펙션이 테스팅 대체 불가능
  • 시스템 컴포넌트 간 상호작용, 타이밍, 성능

[테스트 케이스] : test case

  • 테스트 케이스 : 무엇을 테스트하는지 테스트 입력-예상 출력에 대한 서술
  • 테스트 데이터 : 시스템 테스트 위한 입력
  • 테스트 결과 : 테스트 데이터 입력에 따른 출력

[테스팅의 3단계]

▶개발 테스팅 (development testing)

  • 버그와 결함 찾기 위해 ‘개발 중 테스팅’
  • 시스템 설계자, 프로그래머가 수행

▶릴리스 테스팅 (release testing)

  • 요구사항 만족되는지 시스템 완성 버전 테스팅
  • 별도의 테스트팀이 수행

▶사용자 테스팅 (user testing)

  • 시스템 인수 여부 결정
  • (잠재적) 사용자들이 자신의 환경에서 시스템 테스팅

[테스트 자동화] : Test automation

▶자동화된 테스팅

  • 테스트 실행하는 프로그램 이용
  • 테스트 주도 개발(TDD)를 위해서는 자동화된 테스팅이 필수임

▶회귀 테스팅(regression testing) **

프로그램 변경 후 새 버그 생겼는지 여부 점검 위해 이전 과정에 수행한 테스트 다시 수행

8.1 개발 테스팅

[개발 테스팅의 세 단계]

▶[1. 단위 테스팅] : unit testing

  • 함수, 클래스 등 프로그램의 단위(모듈)를 테스팅
  • 단위의 기능 테스팅에 집중

▶[2. 컴포넌트 테스팅] : component testing

  • 단위들이 통합된 복합 컴포넌트를 테스팅
  • 컴포넌트의 인터페이스 테스팅에 집중

▶[3. 시스템 테스팅] : system testing

  • 시스템 전체로서 테스팅
  • 컴포넌트 상호작용 테스팅에 집중

[개발 테스팅 목표]

  • 주로 버그 발견용. 결함 테스트

    < 참고>

[개발 테스팅 분류]

▶단위(unit) 테스팅

  • 모듈 기능 테스트
  • 테스트 드라이버, 스텁 필요

▶통합(integration) 테스팅

  • 모듈 간 상호작용 테스트
  • 모듈 통합 방법(빅뱅/하향식/상향식)

▶시스템(system) 테스팅

  • 시스템 기능 테스트
  • 요구사항 만족 여부 테스트

-디버깅과 중첩됨

[1. 단위 테스팅] : Unit testing

▶단위 테스팅에서는 개별적인 컴포넌트를 테스팅

  • 함수, 메소드, 클래스 등의 기능 테스트

▶[일반적인 지침]

  • 클래스의 모든 오퍼레이션 테스트
  • 객체가 가질 수 있는 모든 상태를 거치도록 테스트 (모든 상태 전이 순서를 테스트)
  • 상속된 오퍼레이션은 사용된 모든 곳에서 테스트 (클래스 상속이 테스팅의 복잡도 높임)
  • JUnit 등의 테스트 자동화 프레임워크 사용

▶컴포넌트 분리 테스트 위해 ‘모형 객체’ (mock object) 필요

[2. 단위 테스트 케이스 선정]

▶효과적인 단위 테스트

  • 검증: 컴포넌트가 예상(명세) 대로 동작하는 것을 보임
  • 결함: 결함 찾음

▶[테스트 케이스 선정 전략]

▸[동등 분할 테스팅] *****

  • 공통 특성 가진 입력 그룹 식별하여 각 그룹별 테스트 케이스 선정

    ▸가이드라인 기반 테스팅

  • 프로그래머가 자주 범하는 오류 발견을 위한 테스트 케이스 선정

    ▸[코드 커버리지] *****

  • 소스 코드 중 테스트 된 비율

  • 문장 커버리지/ 결정 or 분기(decision or branch) 커버리지/조건 커버리지 등

[분할 테스팅] : Partition testing ★★

▶[동등 분할(eqivalence partition) ] ★

  • 입력 데이터 또는 출력 결과를 공통 특징 가진 그룹으로 분할

▶[분할 테스팅] ***** ★**

  • 입력과 출력 분할을 식별 (동등 분할)
  • 각 분할에서 테스트 케이스 선정
  • 일반적으로 분할 경계와 분할 중간점을 선정

[블랙박스, 화이트 박스 테스팅] Black box & white box testing

▶[블랙박스 테스팅] ★

  • 테스트 케이스 선정을 위해 시스템(테스팅 대상)의 ‘명세’만을 사용
  • 코드나 시스템 내부 지식 X 테스트 케이스 선정
  • 기법: 동등분할

▶[화이트박스 테스팅] ★ = structural testing

  • 알고리즘, 소스코드 등 시스템 ‘내부 구조’를 고려하여 테스트 케이스 선정
  • 기법 : 문장 커버리지/ 분기 커버리지/ 단순 경로

[테스팅 지침] Testing guidelines

시퀀스(배열, 리스트 등) 테스팅 지침

  • 원소가 하나인 시퀀스로 테스트
  • 테스트마다 서로 다른 크기 가지는 시퀀스 사용
  • 시퀀스의 첫 번째, 중간, 마지막 원소를 접근하도록 테스트
  • 길이가 0인 시퀀스(원소가 없는)로 테스트

✅일반적인 지침

  • 모든 오류 메시지가 생성되도록 입력값을 선택
  • 버퍼 오버플로우가 일어나도록 입력을 선정
  • 같은 입력 또는 같은 입력 순서를 여러 번 반복
  • 유효하지 않은 출력이 생성되도록 함
  • 계산 결과를 너무 크거나 너무 작게 되도록 함

[JUnit & EclEmma를 이용한 테스팅 실습]

[흐름 그래프] : Flow graph

▶[흐름 그래프]

  • 프로그램 내의 ‘경로’를 보여줌

▶[순환 복잡도]

  • 프로그램에 존재하는 독립적인 경로의 수
  • 경로의 조합은 고려하지 않음
  • 흐름 그래프를 이용한 계산
  • 순환복잡도 = 간선의 수 – 노드의 수 + 2 = E – N + 2
  • 조건의 수 이용 계산
  • 순환복잡도 = 단순 조건의 수 + 1

▶[기본 경로 테스팅] : basic path testing = 화이트박스 테스팅. 단순 경로 테스팅.

  • 독립적인 경로를 적어도 한 번은 거치도록 테스트 케이스 선정

1) if/else if 조건과 return에 번호 붙임 (단, else에는 번호 안붙임)

2) ‘전체 메소드’ 마지막 } 에도 번호를 붙임

3) 따로 분기문 없는 덩어리는 모두 1개로 침

//소스코드에 번호 잘 붙일 것.

//순환 복잡도 = E-N+2 = 단순 조건의 수 + 1

[3. 컴포넌트 테스팅]

[컴포넌트 테스팅] Component testing

컴포넌트 테스팅

  • (복합) SW 컴포넌트는 상호작용하는 객체들로 구성
  • 컴포넌트의 테스팅은 컴포넌트의 인터페이스를 테스트하는데 집중

: 개별 객체의 단위 테스트는 완료되었다고 가정

: 컴포넌트 인터페이스 오류는 복합 컴포넌트를 구성하는 객체들 간의 상호작용 오류에 기인

인터페이스 유형

  • 매개변수(parameter) 인터페이스
  • 공유 메모리(shared memory) 인터페이스
  • 프로시저(procedure) 인터페이스
  • 메시지 전달(message passing) 인터페이스

[인터페이스 오류] Interface errrors

인터페이스 오용 (misuse)

  • 호출 사용법 관련 오류
  • 예: 매개변수 유형 오류, 매개변수 순서 오류 등

인터페이스 오해 (misunderstanding)

  • 인터페이스 명세를 잘못 이해
  • 예:이진 탐색 함수에 정렬되지 않은 배열을 전달

타이밍(timing) 오류

  • 공유 메모리나 메시지 전달 인터페이스를 사용하는 경우 일어남
  • 예: 생산자/소비자의 속도 또는 타이밍 오류

[인터페이스 테스팅 치짐] Interface testing guidelines

인터페이스 오류를 발견하기 위한 일반적 테스팅 지침

1) 매개변수 값이 범위의 극단(경계)에 있게 테스트를 설게

2) 포인터나 레퍼런스를 사용할 경우 널 객체가 전달되는 경우를 테스트

3) 고의적으로 컴포넌트가 실패하도록 테스트를 설계

4) 메시지 전달 시스템에서 스트레스(stress) 테스팅을 사용

: 타이밍 문제를 발견하는 효과적 방법

5) 공유 메모리를 이용하는 경우 컴포넌트들이 활성화되는 순서가 바뀌도록 테스트를 설게

인터페이스 오류를 찾는데 인스펙션(inspection)이 더 효과적일 수 있음

= 정적인 검증기술 cf. 테스팅은 동적(실행 필수)

[4. 시스템 테스팅]

[시스템 테스팅] System testing

시스템 테스팅

  • 재사용 컴포넌트, 기성품 시스템, 다른 팀에서 개발한 컴포넌트를 통합하여 완전한 시스템을 테스트

시스템 구성요소들의 상호작용을 테스팅하는데 중점

  • 시스템의 창발적 (emergent) 특성을 테스트
  • 계획된 창발적 행동/예기치 못한 창발적 행동

유스케이스 기반 테스팅이 효과적

  • 요구사항에서 작성한 유스케이스 시나리오 -> 시스템 테스팅에 이용
  • 유스케이스 시나리오 표현 : 시퀀스 다이어그램, 액티비티 다이어그램, 자연어 등
  • 기본(basic) 흐름, 대안(alternative) 흐름, 예외(exceptional) 흐름을 고려

8.2 테스트 주도 개발

[테스트 주도 개발] TDD test-driven development

테스트 주도 개발(TDD)

  • 테스팅과 코드 개발이 중첩되어 있음
  • 점증적인 접근법으로 증분(increment)의 테스트를 작성하고 코드를 개발
  • 애자일 기법인 XP에서 시작됨

: 테스트 우선 개발. Test First Development

TDD 프로세스 단계

1) 증분을 위한 기능 식별

2) 테스트를 작성하여 자동화된 테스트로 구현

3) 이전의 모든 테스트와 함께 추가한 테스트를 실행(실패)

4) 증분의 기능을 구현하고 테스트를 다시 실행

5) 모든 테스트를 통과하면 다음 증분을 개발

[테스트 주도 개발의 장점]

테스트 주도 개발의 장점

  • 코드 커버리지(code coverage) : 모든 코드와 연관된 테스트가 있음
  • 회귀 테스팅(regression testing) : 모든 테스트를 실행
  • 단순화된 디버깅 : 문제를 지역화하기(localize) 쉬움
  • 시스템 문서화 : 테스트를 보면 코드를 이해하가 쉬움

회귀 테스팅

  • 시스템을 변경한 후 변경과 관련된 테스트뿐만 아니라 기존에 성공한 모든 테스트를 실행
  • 변경으로 인하여 새로운 버그가 생기지 않았고 새로운 코드가 기존 코드와 문제없이 동작하는지 검사
  • JUnit 등 자동화된 테스팅 필요

8.3 릴리스 테스팅

[릴리스 테스팅] Release testing

릴리스 테스팅은 시스템 테스팅의 한 형태

릴리스 테스팅과 시스템 테스팅의 구분

  • 개발팀이 아닌 ‘별도의 팀’이 테스팅 해야 함
  • 시스템이 요구사항을 만족시키는 것을 점검
  • 시스템이 사용하기에 충분하다는 것을 확인
  • 시스템 테스팅은 결함 테스팅에 중점

블랙박스 테스팅 프로세스

  • 테스트 케이스를 시스템 명세를 이용하여 작성
  • 시스템의 기능만 고려하고 구현은 고려하지 않음

[1. 요구사항 기반 테스팅] Requirements based testing

요구사항 기반 테스팅

  • 검증 테스팅
  • 추적 가능성(traceability) 기록 관리

[2. 시나리오 테스팅] Senario testing

시나리오 테스팅

  • 시스템을 사용하는 전형적인 시나리오
  • 유스케이스 시나리오
  • 한 시나리오 내에서 여러 요구사항을 테스팅 -> 요구사항의 조합 점검

[3. 성능 테스팅] Performance testing

성능 테스트

  • 시스템의 운영 프로파일을 반영하여 트랜잭션 유형의 비율에 따라 테스트
  • 시간 당 처리량(throughput, Transaction per second: TPS), 응답시간(response time) 등을 측정

스트레스 테스팅 Stress testing *****

  • 시스템의 최대 설계 부하를 초과하는 요청을 생성하여 테스트

스트레스 테스팅의 목적

  • 시스템의 장애 행동을 관찰
  • 시스템의 결함(defect)을 발견

8.4 사용자 테스팅

[사용자 테스팅] User testing

릴리스 테스팅 후에도 사용자 테스트는 필수적임

  • 사용자 운영환경이 시스템의 신뢰성, 성능, 사용성, 견고성 등에 영향

사용자 테스팅의 유형

  • 알파 테스팅(alpha testing)

: 사용자가 개발자와 함께 개발자 사이트에서 테스트

: 현실적인 테스트를 설계할 수 있도록 사용자들이 정보 제공

  • 베타 테스팅(beta testing)

: 고객 또는 큰 규모의 사용자 그룹이 시스템을 사용해보고 문제점 피드백

: 다양한 설정과 운영 환경에서 사용되는 시스템을 테스트하는데 효과적

  • 인수 테스팅(acceptance testing)

: 시스템의 인수를 결정하기 위해 고객의 환경에서 고객의 데이터를 이용

: XP에서는 별도의 인수 테스팅이 없을 수도 있음

728x90