Intro
오류와 결함을 검출하고 요구사항에 맞게 작동하는지 검증
기능개발이나 리팩토링으로 인해서 문제가 발생하지 않는지 확인하는 기법
내 코드에 대한 자신감
버그수정 기능추가 리팩톨이 부담감
부채가 늘어나면 파산하게 된다. => 새로운 코드가 더 나을지도
다양한 테스팅 용어가 있지만, 프론트엔드에서 자주언급되는 테스팅
테스팅 트로피
Static 테스트
코드를 실행하지 않고 잡는 것
eslint typescript 등
Unit 테스트
작은 단위를 떼어 내어 분리된 환경에서 테스트
복잡한 알고리즘이 제대로 동작하는지 확인
Mocking 필요
작성 비용 낮음
실행 속도 빠름
ex) Jest
Integration 테스트
어플리케이션의 여러 부분들이 통합되어 제대로 상호작용 되는지 테스트
주로 단위 테스트보다 큰 범위(페이지)의 테스트를 의미
앱의 모든 기능이 제대로 동작한다는 확신을 줄 수 있다.
ex) Jest RTL(React Testing Library), Enzyme
E2E 테스트
실제 사용자가 사용하는 것과 같은 조건에서 전체 시스템을 테스트를
API 서버, DB 등의 외부 서비스들을 모두 사용하여 통합된 시스템을 테스트
비용도 많이들고, 속도도 느림
ex) Cypress, Selenium
왜 통합테스트 비중이 제일 높은가
유닛 테스트만 하면 UI 테스트를 할 수 없다.
Service 테스트가 프론트엔드에 적합
테스트를 작성해라
너무 많이 말고
테스트 커버리지가 70프로 이상이면 하지 않아도 되는 것을 하는 것일 수도 있다.
단위가 잘되어도 통합이 안되는 경우가 있으니 통합테스트 위주로 하는 것이 좋다.
시각적 요소를 테스트하는 방법
- 스냅샷 테스트
- 시각적 회귀 테스트(storybook)
TOAST UI에서
- 크로스 브라우징 테스트가 '반드시' 필요한 경우 브라우저 환경을 사용한다.
- 브라우저의 실제 동작(렌더링, 네트워크 IO, 내비게이션들)에 대한 테스트가 필요한 경우 브라우저 환경을 사용한다.
- 그 외의 경우 Node.js 환경을 사용한다.
테스트 더블이란?
다른 객체에 의존성이 있는 객체들은 테스트 하기 어렵다. 테스트 시 만약 의존성이 있는 객체의 진짜 인스턴스를 사용하면 이 의존성이 있는 객체에 테스트가 영향을 받게 된다. 이를 해결하기 위해 가짜 객체를 사용하는데 이를 Test Double이라 한다.
즉, 테스트 더블은 테스트하고자 하는 대상만 독립적으로 테스트할 수 있도록 별개로 구현한 실제 객체보다 단순한 객체를 의미한다. 테스트 대상을 SUT(System Under Test)라고하고, SUT가 의존하고 있는 구성요소를 DOC(Depended-on Component) 라고 하는데, 테스트 더블은 이 DOC와 동일한 API를 제공한다.
Spy는 테스트에 사용되는 객체, 메소드의 사용 여부 및 정상 호출 여부를 기록하고 요청 시 알려줍니다.
Fake
Fake는 테스트를 위한 가짜 구현을 하는 방식이다. 예를 들어 DB에 저장하는 코드를 가진 클래스가 있다고 하면 이를 메모리에 대신 저장하는 방식으로 가짜 구현을 한다. 즉, 프로덕션의 구현에 영향을 받지 않고 구현을 하는 것이다.
Stub보다는 조금 더 실제 인스턴스와 비슷하게 동작하지만, 미리 준비한 결과를 전달하는 것이 아니라 실제 인스턴스처럼 동작하도록 비즈니스 로직이 추가됩니다.
Stub
Stub은 미리 정의된 데이터를 반환한다. 즉, 테스트를 할 때 요청에 대한 응답을 정해놓는다.
Mock
Mock은 테스트 중의 interaction을 기록한다. 위에서 Stub의 코드에서 interaction이 일어나는 것을 기록하는 것이 바로 Mock 객체이다.
상태 기반 테스트(state base test)와 행위 기반 테스트(behavior base test) 차이점Permalink
- 상태 기반 테스트(state base test) - 객체의 상태가 변했는지 확인
- 행위 기반 테스트(behavior base test) - 객체가 특정 동작을 수행했는지 확인
상태 기반 테스트는 Fake를 이용한 테스트 방식을 예로 들수 있습니다. 특정 데이터를 저장하고, 해당 데이터가 존재하는지 변경된 상태를 확인합니다. 행위 기반 테스트는 Spy를 이용한 테스트 방식을 예로 들수 있습니다
Assertion
어써션이란
프로그램의 특정 지점에 위치한 어써션은 해당 지점에서 개발자가 반드시 참(true)이어야 한다고 생각하는 사항을 표현한 논리식이다. 어써션이 위반되는 경우(즉, 논리식 결과가 거짓)는 프로그램에 버그나 기타 문제가 있는 것을 암시한다.
테스트 원칙
DRY 원칙을 지키세요
beforeEach/afterEach를 사용해서 여러 테스트에서 반복되는 코드 블록과 유틸리티 기능에 대한 로직을 캡슐화합니다.
이유
공유되는 로직이 한 곳에 있으면 쉽게 포함하고 업데이트할 수 있습니다.
beforeEach/afterEach 코드 블록 내에서 자동으로 호출되는 경우, 일반적인 설정/해제(setup/teardown) 논리를 잊어버릴 가능성이 적습니다.
반복을 줄이면 테스트를 더 짧고 읽기 쉽게 만들 수 있습니다.
describe 블록에서 관련 테스트를 그룹화하기
이유
제목이 좋은 describe 블록은 관련 테스트를 그룹으로 분리하여 테스트 파일을 구성하는 데 도움이 됩니다.
단일 describe 블록의 경우, beforeEach/afterEach를 추가하여 테스트의 하위 집합에 특정한 설정/해제(setup/teardown) 로직을 캡슐화하기 더 쉽습니다. (위의 "DRY 원칙을 지키세요" 규칙 참조)
내부 describe 블록은 외부 describe 블록에서 설정 로직을 확장할 수 있습니다.
단위 테스트는 실패할 이유가 하나만 있어야 합니다.
이유
이름에서 알 수 있듯이 단위 테스트는 코드의 단일 "단위"만 테스트해야 합니다.
하나의 실패 이유만 있는 경우, 테스트 실패의 근본 원인을 식별하는 데 소요되는 시간이 줄어듭니다.
SOLID 사례의 단일 책임 원칙을 따릅니다.
더 짧고 읽기 쉬운 단위 테스트를 권장합니다.
테스트를 독립적으로 유지하기
이유
한 테스트의 결과는 다른 테스트에 영향을 미치지 않아야 합니다.
테스트 간에 상태 또는 mock 인스턴스를 공유하면 잘못 통과하는 취약하거나 "깨지기 쉬운(flaky)" 테스트로 이어질 수 있습니다.
새 테스트가 추가되거나 테스트 순서가 변경되면 종속 테스트가 예기치 않게 실패할 수 있습니다.
다양하게 입력되는 매개변수 테스트하기
이유
이상적으로 테스트는 테스트 중인 코드를 통해 가능한 모든 코드 경로를 확인해야 합니다.
우리는 배포된 코드가 사용자가 입력할 수 있는 모든 입력을 처리할 수 있다고 확신하고 싶습니다.
우리는 올바른 것으로 알고 있는 코드 경로를 트리거하는 입력을 사용하여 테스트하는 쪽으로 편향될 수 있습니다. 입력 범위를 테스트하면 우리가 고려하지 않았을 수도 있는 엣지 케이스를 확인하는 데 도움이 될 수 있습니다.
결론
요약하자면, 이 블로그에서는 프런트엔드 테스트에서 다음과 같은 방법의 이점과 자바스크립트/Jest의 예제 테스트에 적용하는 방법을 설명했습니다.
테스트에 린트 규칙 사용하기
DRY 원칙을 지키세요
describe 블록에서 관련 테스트를 그룹화하기
단위 테스트는 실패할 이유가 하나만 있어야 합니다.
테스트를 독립적으로 유지하기
다양하게 입력되는 매개변수 테스트하기
- [번역] 프런트엔드 단위 테스트 모범 사례
- Front-End Testing is For Everyone
- Front End Testing: A Beginner’s Guide
- Front-End 프로젝트의 Test Code 작성 경험기