일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- k8s
- 타입스크립트
- TypeScript
- 파이썬
- 가상화
- 클라우드
- 블록체인
- react
- 프론트엔드
- kubernetes
- 솔리디티
- docker
- HTML
- BFS
- 리액트
- 이슈
- 백준
- JavaScript
- 이더리움
- next.js
- 쿠버네티스
- AWS
- 웹
- CSS
- es6
- 알고리즘
- 자바스크립트
- 컴퓨터공학
- VUE
- 백엔드
- Today
- Total
즐겁게, 코드
프론트엔드 테스팅 첫걸음 : jest 사용하기 본문
테스팅의 중요성
지금까지 프로젝트를 혼자 진행하면서는 print
나 console.log()
등의 출력을 통해 비교적 단순한 '테스트' 를 진행할 수 있었지만, 어플리케이션의 규모가 커지고 동일한 테스트를 반복해야 하는 상황에서는 테스트 코드를 작성하는 것이 필수적입니다.
이번에는 자바스크립트의 강력한 테스팅 라이브러리 jest
와 리액트 프로젝트용 테스팅 라이브러리 react-testing-library(RTL)
을 통해 기초적인 테스트 방법에 대해 알아보겠습니다.
jest 설치하기
리액트 테스팅을 경험하기 전에 일반 자바스크립트 환경에서 jest
를 알아보도록 하겠습니다.
이를 위해 npm init -y
로 프로젝트를 초기화하고, jest
와 @babel/preset-env
를 개발 의존성 파일로 설치합니다.
npm init -y
npm i -D jest @babel/preset-env
잠깐 @babel/preset-env
에 대한 설명을 덧붙이자면 테스트는 node.js
환경에서 이루어지는데요, 따라서 기본적으로는 테스트 코드에서 import
등의 ES6 문법을 사용할 수 없습니다.
이를 해결하기 위해 @babel/preset-env
트랜스파일링 프리셋을 설치하고, 관련 바벨 설정을 먼저 해줘야 합니다.
[루트 경로에 파일 생성 - babel.config.js]
// babel.config.js 파일은 프로젝트 루트 경로에 위치시킵니다.
// .babelrc와 헷갈리시면 안됩니다!!
module.exports = function (api) {
api.cache(true);
return {
presets: ["@babel/preset-env"],
};
};
****
이제 jest
를 사용할 준비가 끝났습니다!
테스트 파일 작성하기
테스팅 파일은 파일명.test.js
또는 파일명.spec.js
처럼 중간에 test
라는 이름이 하나 더 붙습니다.
(예를 들어, addNumber.js
를 테스트하는 테스트 코드의 파일명은 addNumber.test.js
가 됩니다!)
jest
는 기본적으로 __test__
라는 폴더에 존재하는 파일이나, .test.js
또는 .spec.js
로 끝나는 모든 파일을 테스트 파일로 인식하고 실행합니다.
첫 번째 테스트 코드
그럼 첫 번째 테스트 코드를 작성할 간단한 함수를 만들어 보겠습니다.addNumber.js
라는 파일에 두 수의 합을 구하는 함수를 정의한 뒤, 테스트 코드 내에서 이를 사용할 수 있도록 export
로 내보내 줍니다.
// addNumber.js
export const addNumber = (a, b) => {
return a + b;
};
다음은 테스트 코드에서 이 함수가 제대로 동작하는지 확인할 차례입니다.addNumber.test.js
라는 파일을 만들고, 다음과 같이 test()
함수를 작성해 봅니다.
// addNumber.test.js
test("addNumber는 두 수를 더하는 함수입니다.", () => {
})
테스트 실행하기
jest
커맨드만으로도 모든 테스트 코드를 실행할 수 있지만, 두 가지 유용한 플래그가 있습니다.
--coverage
: 프로젝트의 테스트 커버리지를 함께 나타내줍니다.--watch
: 대상 코드나 테스트 코드에 변경이 생기면 테스트를 다시 실행합니다. (nodemon
을 생각하시면 됩니다!)
이제, jest --watch --coverage
로 테스트를 실행해 보겠습니다.
첫 번째 테스트가 실행된 모습인데요, jest
는 테스트 코드 내에서 오류가 발생할 때만 테스트를 fail
시키기 때문에 테스트 코드를 작성하지 않아도 테스트를 통과할 수 있었습니다.
잠깐 다른 이야기
'테스트 주도 개발(Test Driven Development)' 이라는 테스트를 토대로 기능을 구현해나가는 유명한 개발 방법론이 있습니다.
"실패-성공-리팩토링 의 반복" 으로 표현되는 이 방법론은 다음처럼 적용할 수 있습니다.
1. 완벽한 테스트 케이스를 먼저 설계한다.
2. 제작할 함수의 기능을 해당 테스트케이스에 맞춘다.
3. 로직을 개선하면서 1 ~ 3을 반복한다.
어디까지나 제 생각이지만, 저는 개인적으로 좋은 개발 방법이라고 생각해 실제 함수보다 테스트 코드를 먼저 작성하는 습관을 가지면 좋을 것 같다고 추천드립니다!
TDD에 대한 설명은 벨로퍼트님 블로그에 쉽고 자세히 설명되어 있습니다!
다시 돌아와서 - 테스트 작성하기
이제 테스트 코드를 작성해 보겠습니다.
테스트 코드는 test
함수의 두 번째 인자로 주어지는 함수에 작성합니다.
import { addNumber } from "./addNumber.js";
test("addNumber는 두 수를 더하는 함수입니다.", () => {
})
테스트는 "A 조건에서 B를 실행했을 때 예상했던 결과 C가 나오는가?" 의 흐름을 따라가는 것이 권장되는데요, (이를 Arrange - Act - Assert(AAA)
패턴이라고 합니다.) 한번 이 흐름대로 코드를 작성해 보겠습니다.
먼저 조건을 정의해 보겠습니다. (Arrange)
- 테스트 조건 :
addNumber(a, b)
에 2와 3을 전달하면, 결과물은 5가 될 것이다.
import { addNumber } from "./addNumber.js";
test("addNumber adds two number", () => {
// 조건
const numberA = 2;
const numberB = 3;
const result = 5;
})
다음은 코드를 실행합니다. (Act)
- 실행 :
addNumber(a, b)
함수에 2와 3을 전달한다.
import { addNumber } from "./addNumber.js";
test("addNumber는 두 수를 더하는 함수입니다.", () => {
// 조건
const numberA = 2;
const numberB = 3;
const result = 5;
// 실행
const actResult = addNumber(numberA, numberB);
})
마지막으로, 실행 단계에서 실행한 코드를 평가합니다. (Assert)
import { addNumber } from "./addNumber.js";
test("addNumber는 두 수를 더하는 함수입니다.", () => {
// 조건
const numberA = 2;
const numberB = 3;
const result = 5;
// 실행
const actResult = addNumber(numberA, numberB);
// 평가
expect(actResult).toBe(result);
})
두 수를 구하는 addNumber
함수가 주어진 테스트를 통과한 모습입니다!
expect(actResult).toBe(result);
그런데, 실행 단계에서는 뭔가 신기한 문법이 사용된 것 같습니다.
matcher 함수
// = actResult 값이 result와 같을 것이다.
expect(actResult).toBe(result);
테스트를 평가하는 단계에서는 expect()
함수와 matcher 함수가 필요합니다. (절대 어렵지 않습니다!)expect()
함수에는 평가할 값을 인자로 전달하고 해당 값이 특정 조건을 만족하는지를 matcher 함수로 검사하는 것입니다.
주요 matcher 함수
당연하지만 모든 matcher를 외우는 것은 비효율적인 일이고, 아래의 matcher들로도 대부분의 평가가 가능할 것이라 생각됩니다.
(이보다 복잡한 matcher가 필요하다면 공식 문서에서 확인하는 것을 추천드립니다!)
toBeDefined()
함수 : 값이undefined
가 아닌지 검사한다. (주로 가장 먼저 검사한다!)toBe()
함수 : 원시형 데이터를 비교한다.toEqual()
함수 : 참조형 데이터를 깊은 비교를 통해 비교한다.toBeTruthy()
함수 : 값이 참인지를 검사한다..toContain()
함수 : 특정 요소가 배열 안에 존재하는지를 검사한다.not
: 다른 매쳐 함수 앞에 체이닝해 사용하며, 해당 값의 반대값이 참인지를 검사한다.- 주의 :
not
은 함수가 아닌 프로퍼티입니다!
- 주의 :
'🎨 프론트엔드 > Testing' 카테고리의 다른 글
프론트엔드 테스팅 네 번째 걸음 : 리액트 테스팅 (0) | 2021.08.23 |
---|---|
프론트엔드 테스팅 세 번째 걸음 : 목업 테스팅 (0) | 2021.08.20 |
프론트엔드 테스팅 두 번째 걸음 : 비동기 코드 테스팅 (0) | 2021.08.19 |