1. 소프트웨어 테스트란
소프트웨어를 배포하기 전
해당 소프트웨어가 정상적으로 작동하는가에 대해 검증하는 단계
테스트의 종류: 3가지
유닛 테스트, 통합 테스트, 인수 테스트
--> 프로그래밍적으로 수행가능하기 때문에
자동화 처리가 가능
이후 QA 통해 테스터가 직접 소프트웨어를 테스트
이전 직장에 QA, RA 부서가 바로 앞에 있고,
프로그래밍 팀 - SW - HW - V&V (verify, validate) - marketing clinic (임상) - QA, RA 가 있어서
흥미로웠다.
QA는 외주 혹은 개별 팀에서 진행하는 사항이기 때문에
여기에서는 자동화 할 수 있는 테스트 방식에 집중하여 살펴보겠습니다.
테스트 전체 형태
아래 피라미드처럼 구성합니다.
1. 단위테스트, 유닛 (Unit) 테스트
Did we build it right? (빌드를 올바르게 수행할 수 있는가에 대해서 집중)
각 함수 및 클래스 단위로 진행할 수 있기 때문에 가장 많은 수를 차지
개별적인 테스트들이 통과할 수 있다면 여러 테스트를 결합하여 그 결과들을 검증할 수
소프트웨어를 단위로 분해하여 테스트하는 방식을 의미합니다. 나눌 수 있는 단위로 함수 및 클래스를 주로 이용합니다. 모든 코드가 테스트 하기 쉽게 만들어지는건 아닙니다. 다시 말해, 단위가 나눠져있는 상태로 개발되는 것이 아니기 때문에 단위로 나누는 과정을 통해 개발 품질을 높일 수 있습니다. 이를 모듈화라고도 하는데 테스트 가능하게(Testable)라는 의미는 모듈화가 잘 되어 있다 라고도 볼 수 있습니다. 단위 테스트는 모듈 하나 하나를 독립적으로 테스트하여 다른 모듈에 영향을 주지 않으면서 안전하게 테스트합니다.
2. 통합(Integration) 테스트
Did we build it right? (빌드를 올바르게 수행할 수 있는가에 대해서 집중)
모듈들을 조합하여 테스트를 구성하기 때문에 통합 테스트의 수가 상대적으로 더 적습니다.
위 단위 테스트들을 모아서 테스트
1) 모듈들을 모아 테스트하는 방법 = 상향식 통합 테스트
예를 들어, 계산기라는 프로그램에서
더하기만 테스트할 경우 해당 테스트는 유닛 테스트이지만
덧셈과 뺄셈을 동시에 테스트한다면 해당 테스트는 상향식 통합 테스트
2) 모듈이 있는 것을 가정하고 테스트하는 방법= 하향식 통합 테스트
예를 들어, 3 layer architecture 중
서비스 모듈을 테스트를 해야할 시 하위 모듈(여기서는 데이터 액세스 모듈)을 stub(가상의 모듈)으로 만들어 테스트
이는 상위 모듈을 테스트 하기 위해
하위 모듈을 있는 것처럼 속여서 테스트
이렇게 하면 하위 모듈에 상관 없이 상위 모듈만 테스트 할 수 있게 됩니다.
3. 인수(Acceptance) 테스트란
Did we build the right thing? (빌드된 소프트웨어가 정상적으로 작동하는가)
통합 테스트에서 더 나아가 실제 환경처럼 맞추어 테스트하는 것을 의미
알파 테스트와 베타 테스트
- 알파 테스트: 폐쇄적인 환경에서 개발자가 통제를 하여 테스트를 진행
- 베타 테스트: 개방적인 환경에서 비교적 자유롭게 테스트를 진행
4. 코드 커버리지란
Did we build the right thing? (빌드된 소프트웨어가 정상적으로 작동하는가)
테스트가 코드를 얼마나 커버하는지에 대한 정도
- 함수(function)
- 구문(statement)
- 조건(condition)
- 분기(branch)
1) 함수 커버리지
총 함수중에 몇 개의 함수가 실행되는 정도
함수가 실행되지 않는다면 다른 커버리지 또한 측정을 할 수 없으므로 테스트들을 포괄하는 개념으로 볼 수 있겠습니다.
함수 커버리지(%) = 실행된 함수 개수 / 총 함수 개수 * 100
2) 구문 커버리지
코드의 하나의 구문이 실행되는 정도
만약, 그 하나의 구문이 실행되지 않으면 테스트가 되지 않았다고 볼 수 있습니다. Javascript 에서 하나의 구문은 보통 세미 콜론(;)으로 구분합니다.
구문 커버리지(%) = 실행된 구문 수 / 전체 구문 수 * 100
3) 조건 커버리지
if 내의 조건들이 true와 false를 가지는 정도
예를 들어, if (a > 0 || b < 0) 이라는 조건이 있을 때, 전체 조건으로 나올 수 있는 경우의 수는 a > 0이 true 일 때와 false, b < 0이 true 일 때와 false 를 조합하여 총 4개가 됩니다. 이 때, a = 1, b = 1로 테스트를 한번 한다면 a > 0 조건은 true, b < 0 조건은 false 값이 됩니다. 여기서 테스트를 그만 둔다면 조건 커버리지는 1개의 조합만 테스트 하였으므로 25%가 됩니다. 여기서 (a = 1, b = -1), (a = -1, b = 1), (a = -1, b = -1) 들을 테스트한다면 조건 커버리지는 100%가 될 것입니다.
조건 커버리지(%) = 각 조건마다 true or false 한번의 개수 / (전체 조건 수 ^ 2) * 100
4) 분기 커버리지
조건으로 인하여 나뉘게 되는 실행 경로
조건이 많아지면 많아질수록
분기 커버리지의 전체 양이 늘어나게 되므로
테스트할 부분들이 많아지게 됩니다.
분기 커버리지(%) = 실행된 분기 수 / 총 분기의 개수 * 100
소프트웨어 테스트의 역사
1. 소프트웨어 테스트 역사
Gelperin과 Hetzel의 진화적 테스팅 모델의 개념에 따르면, 소프트웨어 테스트의 역사는 크게 5가지로 나뉩니다.
- 디버깅 지향 시대 (debugging-oriented period)
- 증명 지향 시대 (demonstration-oriented period)
- 파괴 지향 시대 (destruction-oriented period)
- 평가 지향 시대 (evaluation-oriented period)
- 예방 지향 시대 (Prevention-oriented Period)
디버깅 지향 시대
- 테스팅을 하는 주 목적은 버그를 제거하는데에 있었습니다. 이에 디버깅과 테스팅의 구분이 없었습니다.
증명 지향 시대
- 테스팅의 목적은 소프트웨어의 요구사항을 포함하기 시작하였습니다. 하지만, 이전 시대의 디버깅 목적의 성향이 남아 있는 시대입니다.
파괴 지향 시대
- 파괴 지향 시대부터 테스팅의 목적은 오류를 찾아내는데에 있습니다. 테스팅을 통해 오류가 발생하였다면, 오류를 찾고 수정하는 디버깅이라는 작업으로 나눠지게 되었습니다.
평가 지향 시대입니다.
- 소프트웨어의 개발 생명 주기(waterfall 등의 방법론에 의해)에 포함되었습니다. 검토 활동의 가치가 인식되기 시작하여서 테스트의 중요성이 부각된 시대라고 볼 수 있겠습니다.
예방 지향 시대
- 소프트웨어 개발 전반적인 부분(설계, 디자인, 구현 등)에서 생기는 문제들을 미리 찾아내기 위함으로 테스팅이 진행됩니다.
2. 최근 테스트 방법론 동향
최근에는 TDD라는 개발 방법론이 등장
기존 Waterfall 방식으로는
설계 → 개발 → 테스트 코드 작성으로 진행하였지만
TDD에서는
테스트 코드 작성 → 개발 → 리팩토링 방식으로 진행
그래서 테스트 주도 개발이라고 불리우며 이는 테스트 코드가 설계의 역할을 한다고 볼 수 있습니다.
TDD 방식으로 진행하여 처음 테스트 코드를 작성을 하면
해당 테스트는 통과하지 못합니다.
이는 테스트하는 함수가 정상적으로 구현되어 있지 않기 때문입니다.
이 때, 개발자는 우선 기능이 돌아가게 프로그래밍하여
해당 테스트를 통과하게 만듭니다.
테스트에 통과 하게 만들었다면
그 다음으로 리팩토링하여 기능이 잘 수행될 수 있게 로직을 개선합니다.
이처럼 TDD는 테스트코드를 먼저 작성함으로써 설계한 후,
하드 코딩하여 재빠르게 기능을 구현하고
리팩토링하여 성능 및 안정성을 높입니다.
애자일한 소프트웨어 개발 방법론이 부상함에 따라
TDD 가 나타나게 되었습니다.
테스트를 하는 이유
1. 소프트웨어 품질 검증 및 보장
소프트웨어의 품질 수준을 보장하기 위해서 테스트를 이용
개발 후 잔존해있는 결함 및 버그들을 찾아서 해결
기존 명세대로 프로그램이 개발이 되어 있는지 테스트
인수 테스트를 통해 사용자의 요구사항을 충족 했는지 확인
소프트웨어가 해결해야할 문제를 정확하게 캐치하고 풀어나가는 과정
2. 유지보수시 Human Error 방지
기능 추가, 버그 제거, 리팩토링에 있어서 개발자는 어떠한 이유로든 실수할 수 있습니다.
이 때, 기존에 있던 자동화 테스트 코드가 통과되지 않는다면
실수가 어디서 발생했는지 잡아내어 수정할 수
유지보수를 할 수 없는 소프트웨어는
퇴사자의 소프트웨어가 아니라
테스트 코드가 없는 소프트웨어이다.
테스트 코드를 추가하는 습관을 들여 유지보수하기 쉬운 상태로 만들도록 합시다.
자동화의 중요성
1. 수동(Manual) 테스트
개발자 및 사용자가 직접 테스트
예를 들어,
함수에 입력을 직접 넣어서 결과를 확인
버튼을 눌려 테스트
테스트를 계획하고 수행하고 결과를 내는데까지 과정이 있으며
이 과정들을 거쳐야 온전한 결과를 받아볼 수 있게 됩니다.
수동 테스트는 개발중이거나 배포 직전 QA 때 진행
주로, 사용성을 검증할 수 있는 UI 및 UX 테스트에서 수행
장점: 수동 테스트는 누구나 직관적으로 쉽게 테스트를 실행
단점: 사람이 직접 실행하다 보니 테스트 실행 속도도 느리고 테스트 시나리오에 따라 시간도 오래 걸려서 자주 실행하기가 힘들고, 부정확할 확률
특히, 인력과 시간이 부족할 수밖에 없는 스타트업이나 소규모 기업에서 테스트를 주먹구구식으로 실행 시, 시스템 버그가 생길 확률이 높아집니다.
2. 자동(Automatic) 테스트
그래서 시스템을 테스트할 때 가장 중요한 것 중 하나가 테스트 자동화
시스템 테스트를 최대한 자동화해서
휴먼 에러를 줄이고, 항상 정확하며, 테스트가 반복적으로 자주 실행될 수 있게, 그리고 빠지는 부분이 없이 테스트가 실행될 수 있도록 하는 것이 개발팀의 생산성을 높이고 시스템을 안정적으로 운영할 수 있는 방법
3가지(인수 테스트, 통합 테스트, 단위 테스트)
인수 테스트는 프론트엔드부터 백엔드까지 모든 시스템을 실행시키고 연결해 놓은 상태에서 진행해야되는 테스트이므로 설정하는 시간도 오래 걸리며, 실제 실행 속도도 느리고 자동화하기가 가장 까다롭습니다. 물론 UI 테스트 프레임워크를 사용하여 어느 정도 자동화는 가능하지만 아직 100% 자동화하기에는 화면 렌더링이 웹 디자이너가 의도한대로 렌더링 되는지의 여부는 확인하기 어렵습니다.
그래서 테스트 피라미드 가장 위에 있으면서 테스트 전략중 가장 낮은 비율을 차지합니다.
****프론트엔드 시스템 혹은 백엔드 시스템, 각각을 독립적으로 실행한 후 http 클라이언트 툴을 사용하여 테스트하는 방식도 있습니다.
이는, 인수 테스트 보다는 간단하지만 실제로 시스템을 실행해서 테스트를 진행해야 하므로 여전히 까다로운 부분이 존재합니다.
3. 단위 테스트의 자동화 = 필수
단위 테스트는 개발자가 테스트 코드를 작성하여 코드로 코드를 테스트하는 방법으로
작성하기 쉬우며, 언제든지 실행할 수 있고, 실행 속도도 굉장히 빠르기 때문에 100% 자동화가 가능
또한, 자동화와 더불어 디버깅을 도와준다는 장점이 더해져 소프트웨어를 빌드할 때, 사전에 오류 찾아내어 수정할 수
빌드 전에 단위 테스트를 자동을 수행하는 스크립트를 통해 자동화를 할 수 있으며
이는 빌드 혹은 컴파일 하기 전, 원격 저장소에 코드가 올라가기 전에 검사하여 안정적으로 코드를 관리할 수
이렇게 디버깅 하기 쉽고 100% 자동화가 가능한 단위 테스트는 시스템 테스트 전략중에 가장 많은 비율을 차지합니다.
Summary
- 소프트웨어 테스트에는 단위 테스트, 통합 테스트, 인수 테스트가 있습니다.
- 테스트는 이전에는 디버깅만을 위해서 이뤄졌지만 최근에는 빌드와 품질 검증용으로 사용합니다.
- 테스트 자동화는 초기 들이는 비용에 비해 많은 이점을 가질 수 있습니다.
- 단위 테스트의 자동화 테스트 코드는 꼭 작성하도록 합시다.
출처: https://www.notion.so/wecode/TDD-b04e8ca5f84b402b9c106e37bf46cbce#ef7349d56bc34073a0c8da06880f4db4
'Wecode - Project 3 (부트캠프) > 세션' 카테고리의 다른 글
Software Testing 2) - [TDD] 테스트 실습 + 추후에 따라해보기 ** (0) | 2023.10.27 |
---|---|
이후 해보면 좋을 [계산기 프로그램 리팩토링] 과제 ** (0) | 2023.10.27 |
주니어 개발자 마인드셋 (0) | 2023.10.27 |
Docker를 활용한 AWS 실습 [개념] (0) | 2023.10.26 |
docker 세션 [개념, 명령어, docker file ] (0) | 2023.10.26 |