새로운 발견에 무기부터 만드는게 인간 아니겠습니까? 만들었으면 테스트를 해보는 거고요.
내가 자주 보는 소설 속 악역이 했던 말이다.
하루 평균 약 1시간, 소설을 읽는 시간을 가지는데 마침 테스트 관련 글을 쓸 시간이 되었을 때 이 대사를 읽자마자 개발이 생각났다.
나도..어느 정도 개발자가 되었나보다.
어찌되었든 개발자에게 코드란 무기라고 생각이 되고 이러한 무기가 만들어지면 테스트를 해야 된다. 당연한 절차이다.
그렇다면 테스트는 어떻게 진행되고 어떤 테스트가 있는 것인지 간단하게 알아볼 시간이다.
소프트웨어 또는 특정 기능을 배포하기 전 정상적으로 작동하는가 검증하는 단계이다.
설계자가 요구한 기준에 맞춰 소프트웨어가 제대로 작동하는지 판단
품질 검증을 위한 디버깅
다양한 OS, 플랫폼, 그리고 기기에서도 작동이 잘 되는지
배포 전 여러가지 케이스를 실행해보면서 잠재적인 이슈에 대한 인지
해킹에 대한 사전 방지
사실 이외에도 테스트
라는 워딩에 맞춰 다양한 사유가 있지만 개발자들이 주로 소프트웨어를 테스트 하는 가장 중요한 이유는 디버깅
과 요청 사항에 대한 만족
이라고 한다.
테스트를 진행하는 방식에는 다양한데 사실 여기에 쓴 유닛 테스트
, 통합 테스트
, E2E 테스트
, 그리고 인수 테스트
이외에도 더 많은 것으로 알고 있으나 가장 기본이 되는 4가지 먼저 우선 알아보려고 한다. 그리고 회사에 여건에 따라 테스트를 진행 하지 않는 곳도 있다.
단위 테스트 혹은 유닛 테스트라고 불리우며 소프트웨어를 단위로 분해하여 테스트하는 방식을 의미합니다. 나눌 수 있는 단위로 함수 및 클래스를 주로 이용합니다.
테스트 방식 중 가장 기본적이고 대중적인 테스트 입니다.
예를 들어 한 서비스의 10개의 함수가 있다면 그 함수들을 독립적으로 분리하여 테스트를 진행하는 방식으로 다른 테스트는 진행을 하지 못하더라도 Unit Test만큼은 진행하는 회사가 많다.
통합 테스트란, 위에서 말한 단위 테스트들을 모아서 테스트하는 것을 의미합니다. 예를 들어, 계산기라는 프로그램에서 더하기만 테스트할 경우 해당 테스트는 유닛 테스트이지만 덧셈과 뺄셈을 동시에 테스트한다면 해당 테스트는 상향식 통합 테스트입니다.
쉽게 말해, a-z까지 독립적으로 테스트를 기존에 실행했다면 이번에는 모든 테스트를 연결해서 실행하는 것을 뜻 한다.
E2E 테스트는 실제로 웹 또는 소프트웨어를 사용하는 유저 입장에서 테스트를 진행하며 유저가 실제 소프트웨어를 작동하는 흐름에 따라 데이터도 잘 유지가 되는지 확인할 수 있는 테스트이다.
쉽게 말해, 가상의 유저가 있다는 가정하에 진행되는 테스트라고 보면 된다.
통합 테스트에서 더 나아가 실제 환경처럼 맞추어 테스트하는 것을 의미합니다. 주로 알파 테스트와 베타 테스트로 알려져 있는 테스트들이 인수 테스트에 속합니다. 알파 테스트는 폐쇄적인 환경에서 개발자가 통제를 하여 테스트를 진행하고 베타 테스트는 개방적인 환경에서 비교적 자유롭게 테스트를 진행합니다.
어떻게 보면, E2E 테스트와 헷갈릴 수 있는데, E2E 테스트는 조금 더 기술적인 측면에서 테스트를 진행하면 된다고 생각하면 되고 인수 테스트는 비즈니스적인 요소를 더 본다고 생각하면 된다.
조금 더 쉽게 표현하자면, 누가 테스트를 진행하냐에 메인을 보면 된다.
E2E 테스트 - 유저의 시야에서 개발자가 진행
인수 테스트 - 실제 유저가 직접 진행
테스트를 진행하게되면 코드 커버리지 (Code Coverage)
라는 것을 체크하게 되는데 쉽게 말해 내가 짠 테스트가 전체 로직에서 몇 퍼센트를 테스트 하고 있는 것인지를 보여준다.
코드 커버리지란, 테스트가 코드를 얼마나 커버하는지에 대한 정도입니다. 커버리지는 함수(function), 구문(statement), 조건(condition), 분기(branch) 으로 분류 되어집니다.
실제 위 예제는 Jest
라는 테스트 패키지를 실행하여 UNIT TEST를 진행 하던 중 중간에 살펴본 코드 커버리지이다.
각 각의 서비스 로직에 대한 Unit Test를 작성하였고 지금 보면 users.service.ts의 파일의 커버리지가 100% 즉 거기에 쓰인 모든 로직이 100% 테스트 되었다는 사실을 알 수 있다.
실제 현업에서 업무를 진행하고 있는 사람들에게 문의 결과 1전체 커버리지 100%를 하는 경우는 없다고 한다. 주 기능 위주로 테스트를 진행하며 시간관계상 필요에 따라 차근 차근 진행한다고 한다.
여기까지 위에서 알아본 것들은 테스트 종류에 대해서 알아보았고, 다음에는 실질적으로 테스트를 어떻게 진행하는지 알아볼 차례이다.
크게 수동 테스트와 자동테스트로 나뉘고 각각의 장/단점을 나열해보려고 한다.
수동 테스트는 개발자 및 사용자가 직접 테스트하는 것을 의미합니다. 예를 들어, 함수에 입력을 직접 넣어서 결과를 확인하거나, 버튼을 눌려 테스트를 하는 방법이 있습니다.
개발자 및 사용자가 직접 테스트 (ex 함수에 직접 값을 입력하거나 버튼을 눌러 테스트)
- 장점 : 쉽고 직관적으로 가능
- 단점 : 실행 속도 느리고 시나리오에 따라 자주 실행하기 어려움, 그리고 부정확함
유연성 : 테스트 케이스와 결과 분석에 대해서 비교적 유연하다.
UX : 수동 테스트를 진행 함에 있어 UX를 비교적 직접적을 체험 해 볼 수 있다.
적은 셋업 시간 : 자동 테스트에 비해 셋업 시간이 적고 간단하다.
경제적 : 자동 테스트에 비해 돈이 적게 든다.
기능이 많아질수록 각 각의 기능들을 테스트 하는 것에 비교적 시간이 많이 든다.
휴먼 에러가 발생할 수 있고 정확도가 떨어 질 수 있다.
테스트 커버리지가 상대적으로 빈약할 수 있다.
시스템 테스트를 최대한 자동화해서 휴먼 에러를 줄이고, 항상 정확하며, 테스트가 반복적으로 자주 실행될 수 있게, 그리고 빠지는 부분이 없이 테스트가 실행될 수 있도록 하는 것이 개발팀의 생산성을 높이고 시스템을 안정적으로 운영할 수 있는 방법입니다.
빠른 테스트 : 버튼 하나로 세팅된 테스트를 진행하는 것이기에 상당히 빠르다.
높은 정확성
테스트 케이스의 재활용
높은 코드 커버리지
높은 초기 세팅 및 비용
유지 : 코드가 변경될 때마다 테스트 코드 또한 변경해야 해서 끈임없는 유지 보수가 필요하다.
복잡성 : 진입 장벽이 높다.
TDD는 사실 테스트를 하는 방식이 아니라 애초에 프로그래밍을 기획함에 있어 작업을 시작할 때 정해지는 설계 원칙이다.
기존 작업 방식으로는
설계 → 개발 → 테스트 코드 작성
으로 진행하였지만 TDD에서는 테스트 코드 작성 → 개발 → 리팩토링 방식으로 진행을 합니다. 그래서 테스트 주도 개발이라고 불리우며 이는 테스트 코드가 설계의 역할을 한다고 볼 수 있습니다.
사실 현재 진행하고 있는 프로젝트의 개발 방식으로 TDD로 하려고 하였지만 경험과 기획 부족으로 어려워 원래 기존의 방식을 준수 하기로 하였다.
TDD에 대한 자세한 설명은 본인의 경험 부족으로 인해 실수가 발생할 수 도 있으니 추후 경험을 직접적으로 남기는것에 의의하고 지금은 TDD가 무엇인지만 파악하고 넘어간다.