- 테스트
- level에 따라 - unit, integration, system, acceptance
- method에 따라 - 블랙 박스, 화이트 박스
- type에 따라 - manual, automated
V&V
validation(확인)
: 올바르게 제품을 구축했는가 - 요구사항대로 제품이 동작하는가verification(검증)
: 올바르게 제품을 구축하고 있는가 - 스펙에 부합하는가
테스팅: 의도된 입력 뿐만나이라 의도되지 않는 입력도
- system under test(SUT): 테스트 대상
- expected output: 기대 출력
- test input: 테스트 대상에 테스트 케이스를 입력
- test case: 입력과 기대 출력
- test oracle: 정답을 가지고 있으며 판정도 가지고 있는 것 - 정답의 세트 - 테스트를 통과 했는지 판단
_
케이스 만들기 - 모든 케이스를 테스트 하기에는 많기 때문에 골라서 몇개만 test suite: 테스트 케이스의 집합
_
- error(버그): 코드에 버그로 존재
- fault(defect=결함): 버그란 코드 내부에 결함으로 존재 - 누락된 결함
- failer(실패): 특정 상황에 대해 버그가 외부로 드러남 - 모든 결함이 실패로 이루어지지 않는다.
_
테스팅
이란 제품이 정상적으로 동작한다는 것을 보여주는게 아니라, 에러를 발견하는 과정이다. 좋은 테스팅이란 많은 오류를 발견하는 것이다.
-
- 블랙박스: 입력과 출력만을 보는 테스트 - 요구사항 스펙을 보고 입력을 결정
- 화이트박스: 프로그램의 내부를 보는 테스트 - 코드를 보고 입력을 결정, 그래도 출력은 요구사항 스펙을 보고 결정
- 그레이박스
누군가가 오라클을 줄 수 있으면 입출력을 만들때 요구사항 스펙을 참고하지 않아도 됨.
-
테스팅의 경제성 문제: 모든 경우의 수를 테스팅하는 것은 불가능하다.
-
테스팅 원리 요약
- 테스트 케이스에서 기대 출력은 필수적이다.
- 자기자신의 코드를 테스팅하는 것은 피해야한다.(유닛 테스팅 제외)
- 프로그래밍 조직이 자신의 코드를 테스팅하는 것을 피해야한다.
- 테스팅 과정은 각 테스트 결과에 따른 철저한 검증이 필요
- 테스트 케이스를 만들때 의도된(valid, invalid) 입력 뿐만아니라 얘기치않은(unexpected) 입력도 넣어봐야함
- 일회용 테스팅 케이스를 피하라(회귀시험에)
- 테스팅을 할대 오류가 없다는 것을 검증하기 위해 하지 말아라
- 프로그램에서 에러가 많이 존재하는 부분은
- 테스팅이라는 것은 매우 창의적이고 기능적인 작업
-
정적 시험 Static Testing
정적 시험
이란 실행을 안시키고 하는거동적 시험
이란 프로그램을 실행 시켜 실제 입력을 너보는거
동적 시험과 정적시험의 차이점
- 정적 시험은 개발 산출물(리뷰 등)을 보고 테스팅. 정적 분석은 복잡하므로 툴만 가지고 할것이다.
- 정적 분석은 스펙이 주어지고, 예를들어 상태 차트 다이어그램.
- 정적 테스팅은 보안과 안전이 필요한 시스템에서 많이 함
-
정적 테스트에서 사용되는 산출물
- 요구사항 명세서(기능, 비기능)
- High level design
- Low level design
- 디자인 명세서(시스템 아키텍처(하드웨어 포함), 소프트웨어 아키텍처)
- 코드(코드 리뷰): 인스펙션(코드를 하나씩 보면서)과 워크스루(테스트케이스를 만들어 두뇌시뮬레이션)로 구분
- 유저 가이드
-
개발 단계 별 수행되는 정적 테스트
- 요구사항 분석 -
- 설계 -
- 개발 - 코드의 품질
- 테스팅 - 테스트 케이스에 대한 테스튼
- 유지보수
버그는 일찍 발견할 수록 싸다(나중에는 범위도 커지고) 비용이 선형적으로 커짐 코드리뷰를 자주 하면 코드의 품질 높아짐 > 버그 낮아짐
-
가독성과 코드 컨벤션은 정적 테스팅으로만 확인할 수 잇다.
정적 테스팅은 항항 체크리스트
와 프로세스로 진행된다.
동적 테스팅은 테스트 케이스를 사용. 정적 테스트도 테스트 케이스를 쓰기도함(머리로 돌림)
-
- 설계 결함: 비효율적 알고리즘, 디비 구조, 높은 결합도, 낮은 응집도
- 코딩 결함: 정의되지 않은 값을 갖는 변수, 선언되었지만 사용되지 않은 변수, 접근할 수 없는 변수, 중복 코드.
- 표준을 준수하지않는 경우
- 잘못된 인터페이스 명세
-
모든 품질속성을 충족시킬수 없다(trade off). 따라서 중요한 것을 골라서 해야함.
-
인스펙션 팀(4사람으로 구성)
- moderator(중재자): 프로그래밍 잘하는 사람
- 프로그래머
- 설계자: 폭넓은 지식을 가지는 사람
- 테스트 스페셜리스트
-
오류 종류
- data reference error: 배열 넘어가는 경우
- data declaration error: 데이터 초기화 안하고 사용, 변수 이름이 비슷한가
- computation error: 0으로 나눌때, 다른 타입끼리 연산, 정수끼리 나누는 연산
- comparison error: 1 < a < 2이런거, 실수 비교연산
- control flow error: 루프가 종료가 되는가, off-by-one error
- input/output error: 파일 위치, 권한, rw 모드, EOF 처리
- interface error: 함수 매개변수
Test Case Design
효과적인 테스트 케이스 만드는법
모든 오류를 잡을 수 없고, 모든 테스트 케이스를 검사할 수 없다 - 효율성 필요
- random-input testing: 무작위로 숫자를 넣음
두 가지 테스트 케이스 만드는 주요 방법 - 블랙박스, 화이트박스
- 화이트 박스(구조 기반 시험): 뒤에 커버리지(코드를 얼마나 실행시키는가) 라는 이름이 붙은 여러 종류의 기법을 가짐. 비용이 많이 드는 시험. 명세가 되어 있는데 코드에 없는 경우 알 수 없음.
- 블랙 박스(명세 기반 시험): 동등분할, 경계값 분석, 원인 결과 그래프, 오류. 명세되지 않은 행위를 구현한 부분을 시험할 수 없다.
언제 시험을 끝낼것인가?
test adequacy: 테스트 충분성(테스트를 끝내도 되는 기준)
- 프로그램의 구조(화이트), 프로그램의 입력(블랙), 요구사항들(블랙)
coverage 맹신의 위험성: 보증을 하진 않음. 단지 테스팅을 정량화하는데 사용. 테스트를 안한 부분은 모름. 커버리지를 맹신하면 커버리지를 올리려고 비슷한 테스트 케이스를 만들려는 경향이 놓음.
MCDC pair 만들기
조건에 영향을 주는 여러개의 변수중 하나의 변수가
boundary test
04-1 test case design 사례
널, 빈, 길이1, 길이1이상
null null null
abc ab bc 길이가 겹침 abcd ab cd 길이가 0 ab b a 길이가 -1
- open과 close가 사이에 문자가 0개
- open과 close가 같음
5 test case design 3
6 MBT(Model Based Testing)
상태 전이 테스팅
- 유한 상태에 대한 전이 테스팅
-
Finite State Machine - state, transition, event, action
- All states coverage
- All transitions coverage
- All transition pairs coverage
- path coverage
7 테스트 자동화
테스트 자동화란 소프트웨어를 사용하여 자동으로 실제 결과와 예상 결과를 비교하는 것
- 회귀 테스트: 변경 이후 기존 기능과 새로 추가된 기능 테스트
- 리팩토링: 코드의 복잡도를 낮추는 것
Manual vs Automated
Manual Testing | Automated Testing |
---|---|
사람 실수 발생 가능 | 안정적 |
느림 | 빠름 |
탐색 테스팅, 사용성 테스팅에 적합 | 회귀 테스특와 퍼포먼스 테스트에 적합 |
초기 비용 낮음 | 초기 비용 높음 |
ROI 낮음 | ROI 높음 |
사용자 친화적 |
테스트 자동화 과정
- 자동화 툴 선정
- 자동화 SUT 선정
- 테스트 suite와 script 작성
- 테스트 실행
- 유지보수
JUnit
자바 테스트 자동화 프레임워크
method
- assertTrue (a) : a가 참인지 확인
- assertArrayEquals(a, b) : 배열 a와b가 일치함을 확인
- assertEquals(a, b) : 객체 a와b의 값이 같은지 확인
- assertSame(a, b) : 객체 a와b가 같은 객체임을 확인
- assertNotNull(a) : a객체가 null이 아님을 확인
annotation
- @AfterAll: 테스트 후 한번만 실행
- @BeforeAll: 테스트 전 한번만 실행
- @AfterEach: 각 테스트 케이스 후 실행
- @BeforeEach: 각 테스트 케이스 전 실행
Data-Driven Tests
미리 정의된 입출력 Set을 사용하여 동일한 테스트를 반복
@ParameterizedTest
@CsvSource()
void calTest(){}
8 단위 테스트
- 객체 지향에서 유닛 - 메소드, 클래스
- 절차 지향에서 유닛 - 함수, 한페이지 코드, 4~40시간 분량 코드, 컴파일 가능한 가장 작은 단위
단위 시험 특징
- 코드를 작성한 사람이 수행
- 맥락에서 자유로움
- 프로젝트에서 명시적인 결과물로 간주되지 않음
- 정적 분석과 하면 가장 효과 좋음
- 프로그램 테스트 프로세스에 병렬성 도입
- 일반적으로 비용 많이 듬
- 테스트 드라이버와 스텁이 필요
Test Double
실제로 동작하는 것처럼 보이게 만들어 놓은 dummy 객체
- Dummy: 아무 동작도 하지 않고, 단지 메소드의 시그니처를 맞추기 위해 사용됩니다.
- Fake: 실제로 동작하지만, 프로덕션 환경에서 사용되는 객체와는 다른 단순화된 버전입니다.(in-memory db)
- Stub: 특정 메소드 호출에 대해 하드코딩된 값을 반환하는 객체로, 호출 검증 기능은 없습니다.
- Spy: 실제 객체처럼 동작하면서 호출 기록을 남기는 객체로, 호출 검증이 가능합니다.
- Mock: 호출 기록과 함께 예상 동작을 설정할 수 있는 가장 강력한 테스트 더블입니다.
Mock 프레임워크
- Mockito
Test Driver
테스트할 unit을 호출함
- 테스트케이스 초기화
- 입력 시뮬레이션
- 출력 비교
- 기록
- 디버깅 지원
Test Harness
테스트 실행을 도와주는 테스트 드라이버, 스텁 및 기타 도구
단위 테스트 중지 조건
- 시간이 없을때
- 새로운 Failer와 Fault가 없을때
- 테스트 케이스가 생각이 안날 때
- 의무적인 커버리지 달성
- 모든 fault가 제거되었을 때
9 통합 테스팅
- 컴포넌트 그룹을 테스트
- 유닛들의 상호작용과 그들의 인터페이스를 테스트
- 명세에 대한 잘못된 모듈을 찾는 것이 목적
통합 오류
- 해석 오류: 잘못된 명세 해석으로 모듈의 기능이 잘못됨
- 잘못된 요청 오류: 모듈끼리 요청하는데 오류
- 인터페이스 오류: 모듈의 입출력 형식, 타입
통합 테스트 케이스 선정 기준
- 모듈의 요청
- 모든 가능한 응답
- 파라미터 전달
통합 테스트 종류
- Top-Down Testing(TDT): 테스트 스텁 모듈 사용
- Bottom-Up Testing(BUT): 테스트 드라이버 모듈 사용
- Big Bang Testing(BBT): 한번에 합치기
- Call Graph-Based Testing (CGBT): 메소드의 호출 관계를 그래프로
- Sandwich: top-bottom까지 하나의 패스를 빅뱅처럼 통합. 스텁과 드라이버를 적게 만들 수 있지만 결함 격리가 어려움
- Path-based Integration:
빅뱅의 단점
- 잘못된 인터페이스를 늦게 발견함
- 디버깅이 어려움
- Non-incremental testing은 철저한 테스트가 어려움
incremental testing이 더 우수하다 할 수 있음
TDT vs BUT
|TDT|BUT| |:–:|:–:| |테스트 스텁|테스트 드라이버| |여러 버전의 스텁 필요|드라이버 하나만 있으면 됨| |상위 모듈이 중요할 때|하위 모듈이 중요할 때| |초기에 시연 가능|테스트 출력 관찰 쉬움|
Call Graph-Based Integration
decomposition-based integration의 문제를 해결
- 함수나 메소드 간의 호출 관계를 그래프로 나타냄
- call graph에 호출 순서에 따라 통합(일반적으로 최상위 모듈)
- 모듈 트리에서 나타나지 않은 call을 표현 가능
- 모듈 간의 의존성 명확, 체계적 통합.
Pairwise Integration
- 간선 하나를 테스트
- 스텁, 드라이버없이 실제 모듈 사용
- 호출의 한 쌍을 단위로 테스트 세션 제한
- 호출 그래프 각 간선마다 하나의 테스트 세션 생성
- 결함 격리가 쉽고 두 페어 중 하나에 결함이 존재함을 알 수 있음
- 한 페어를 수정하면 다른 페어가 동작이 안될 수 있음
Neighborhood Integration
- 하나의 노드와 연결된 간선을 테스트
- 통합 테스트 세션의 개수가 작지만, 결함 격리가 어려움
Path-base Integration
- 구조적이면서 행동적인 통합
- 시스템의 모듈 간의 상호작용을 경로를 기반으로 통합
- 시스템 장치 간 상호작용의 중점
10 Higher Order Testing
- 전체 시스템을 테스트
- 코딩 오류보다 설계 오류가 더 많이 발생하기 때문에 필요
과정
- alpha test(functional test, system test): 최종 사용자처럼 테스트
- acceptance test
- beta test(installation test): 고객의 대표자가 테스트
- Open beta: 모든 사람이 테스트 가능
- Closed beta: 제한된 사람만이 테스트 가능
- release
- gamma test(post-deployment test): 제품의 배포가 준비되었는지, 피드백 받음
Functional Testing (System level)
- 기능적 요구사항을 만족하는지
- user case based test
- 반면에 Non-Functional Testing은 신뢰성, 유지보수성, 확장성 등을 검사
System Testing
- programs, documentation, and data를 포함한 많은 산출물로 구성
- 제품에 대한 측정 가능한 목표가 있어야함
- 테스트를 하는데 정해진 방법이 없다 - 창의적이어야함
- 번역 오류에 중점을 둠
형상 테스트(Configuration Test)
소프트웨어가 설치되거나 연결될 하드웨어의 조합 테스트
호환성 테스트(Compatibility Test)
소프트웨어가 다른 소프트웨어와 더불어 작동해도 문제가 없는지
순응 테스트(Comformence Test)
각종 프로토콜, 표준, 지침을 지키는지
Localization Test
번역 이상 없는지
종류
- stress test: 지정된 한계 이상으로 스트레스를 주는것, 메모리 누수
- load test: 최대 부하 조건에서 응용 프로그램이나 시스템의 성능을 확인합니다.
Acceptance Testing
- 초기 요구사항 및 현재 요구사항을 비교하는 시험
- 고객 또는 최종 사용자가 수행
Installation Testing
- 하드웨어에 설치 잘되는지
회귀 시험
- 변경된 사항으로 인해 변경되지 않은 사항이 오작동하지 않는지
- 새로운 테스트를 만들지 않는다.
- 종류
- Re-testing (retest all)
- selective retest
- Test cases prioritization
시험 종료 조건
- 계획된 시험 100% 성공했을 때
- 해결되지 않은 심각한 결함이 없음
- 모든 위험 상황 완화
- 각 테스트 주기마다 2개 미만의 오류
- 회귀 시험 모두 시행
- 중요하거나 회귀 결함이 제거