Test
- 작성한 코드가 잘 작동한다는 것을 검증하는 작업
Test Why?
- 간단하고 더 안정적인 어플리케이션을 위해서는 여러 방법으로 테스트를 해줘야 더 안정적인 어플리케이션이 될 수 있다!
테스트 자동화
- 사람이 직접 확인을 하는 것이 아니라, 테스트를 하는 코드를 작성해서, 테스트 시스템이 자동으로 확인을 해주는 것
장점
- 작성하고 있는 코드가 기존의 기능들을 실수로 망가뜨리는 것을 효과적으로 방지
- 실제 발생할 수 있는 상황에 대하여 미리 정리해놓고 그에 맞춰 코드 작성 시, 우리가 실수로 빠드릴 수 있는 사항들을 까먹지 않고 챙길 수 있다.
- 리팩토링 이후에 코드가 이전과 똑같이 작동하는지 검증하기 쉬워져 코드의 질이 향상
유닛 테스트
- 하나에 초점을 두고, 조그마한 단위로 작성
- 보통 한 파일만 불러와 진행
유닛 테스트 예
- 컴포넌트가 잘 렌더링된다.
- 컴포넌트의 특정 함수를 실행하면 상태가 우리가 원하는 형태로 바뀐다
- 리덕스의 액션 생성 함수가 액션 객체를 잘 만들어낸다
- 리덕스의 리듀서에 상태와 액션객체를 넣어서 호출하면 새로운 상태를 잘 만들어준다
통합테스트
- 여러 요소들을 고려하여 기능들이 전체적으로 잘 작동하는지 확인
- 여러 파일들을 불러와서 사용
- 하나의 파일에 여러 기능들이 함께 사용되는 것
통합 테스트 예
- 여러 컴포넌트들을 렌더링하고 서로 상호 작용을 잘 하고 있다
- DOM 이벤트를 발생 시켰을 때 우리의 UI 에 원하는 변화가 잘 발생한다
- 리덕스와 연동된 컨테이너 컴포넌트의 DOM 에 특정 이벤트를 발생시켰을 때 우리가 원하는 액션이 잘 디스패치 된다
Jest
- FaceBook에 의해서 만들어진 테스팅 프레임 워크.
- 최소한의 설정으로 동작하며 Test Case 를 만들어서 어플리케이션 코드가
잘 돌아가는지 확인해줌.
- 단위 (Unit) 테스트를 위해서 이용.
Jest 시작하기
- Jest 라이브러리 설치 npm install jest --save-dev
- Test 스크립트 변경 "test" : "jest" or "jest --watchAll
- 테스트 작성할 폴더 및 파일 기본 구조 생성
Jest 파일 구조
-
describe: 여러 관련 테스트를 그룹화하는 블록을 만든다.
-
it: 개별 테스트를 수행하는 곳. 각 테스트를 작은 문장처럼 설명.
-
expect: expect 함수는 값을 테스트할 때마다 사용. 그리고 expect 함수 혼자서는
거의 사용 되지 않으며 matcher와 함께 사용.
-
matcher: 다른 방법으로 값을 테스트 하도록 "매처"를 사용.
-
App.test.js: 기본 테스트가 진행되는 곳
-
render 함수
-> DOM에 컴포넌트를 랜더링하는 함수
-> 인자로 랜더링할 React 컴포넌트가 들어감
-> Return은 RTL에서 제공하는 쿼리 함수와 기타 유틸리티 함수를 담고 있는 객체를 리턴(Destructuring 문법으로 원하는 쿼리 함수만 얻어올 수 있다.)
====> 소스 코드가 복잡해지면 비추천 !!! screen 객체를 사용하기 왜냐면 사용해야 할 쿼리가 많아질수록 코드가 복잡해질 수 있음
쿼리 함수
- 쿼리는 페이지에서 요소를 찾기 위해 테스트 라이브러리가 제공하는 방법
- 여러 유형의 쿼리("get", "find", "query")가 존재.
- 이들 간의 차이점은 요소가 발견되지 않으면 쿼리에서 오류가 발생하는지 또는 Promise를 반환하고 다시 시도하는지 여부.
- 선택하는 페이지 콘텐츠에 따라 다른 쿼리가 다소 적절할 수 있다.
get, find, query 의 차이점
getBy...
- 쿼리에 대해 일치하는 노드를 반환하고 일치하는 요소가 없거나 둘 이상의 일치가 발견되면 설명 오류를 발생시킨다.(둘 이상의 요소가 예상되는 경우 대신 getAllBy 사용)
queryBy...
- 쿼리에 대해 일치하는 노드를 반환하고 일치하는 요소가 없으면 null을 반환. 이것은 존재하지 않는 요소를 어설션(개발시에 디버깅을 해주면서 프로그램 배포시에는 컴파일 되지 않게 할수있는 코드)하는데 유용. 둘 이상의 일치 항목이 발견되면 오류가 발생(확인된 경우 대신 queryAllBy 사용)
findBy... (getBy + waitFor)
- 주어진 쿼리와 이리하는 요소가 발견되면 Promise를 반환. 요소가 발견되지 않거나 기본 제한 시간이 1000ms 후에 둘 이상의 요소가 발견되면 약속이 거부된다. (둘 이상의 요소를 찾아야하는 경우 findAllBy사용)
- waitFor: 일정시간 동안 기다려야 할 때 waitFor를 사용하여 기대가 통과할 때까지 기다릴 수 있다.
자바스크립트 테스팅의 기초
자바스크립트 테스트 자동화 도구
- Jest: jasmine을 기반으로 만든 테스팅 프레임워크. (CRA로 만튼 프로젝트에서 자동으로 적용)
- Karma
- Jasmine
- Chai
- Mocha
작업환경 설정
- 디렉터리 생성
yarn init -y
또는
npm init -y
yarn add jest
또는
npm install --save jest
yarn add @types/jest
- Pakage.json에 scripts 추가
{
"name": "tdd",
"version": "1.0.0",
"description": "",
"main": "sum.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@types/jest": "^28.1.7",
"jest": "^28.1.3"
},
"scripts": {
"test": "jest --watchAll --verbose"
}
}
테스트 작성
sum.js
function sum(a, b) {
return a + b;
}
module.exports = sum; // 내보내기
sum.test.js
const sum = require('./sum');
test('1 + 2 = 3', () => {
expect(sum(1, 2)).toBe(3);
});
- test: 새로운 테스트 케이스를 만드는 함수
- expect: 특정 값이 ~일 것이다. (통과시 성공, 그렇지 않을 시 실패 시킨다)
- toBe: matchers라고 불리는 함수, 우리가 정한 값과 일치하는지 확인
(특정 값이 어떤 조건을 만족하는지, 함수가 실행되는지, 에러가 나는지 확인)
test 대신 it
- test와 it은 같은 작동방식을 가지고 있고, it을 사용하게 되면 테스트케이스 설명을 영어로 작성 시 '말이 되게' 작성 가능.(한국어로도 설명 가능)
sum.test.js
const sum = require('./sum');
it('1 + 2 잘 더해진다', () => {
expect(sum(1, 2)).toBe(3);
});
describe 사용
- describe 키워드 사용시 여러 테스트 케이스 묶기 가능
sum.js
function sum(a, b) {
return a + b;
}
function sumOf(numbers) {
let result = 0;
numbers.forEach(n => {
result += n;
});
return result;
}
// 각각 내보내기
exports.sum = sum;
exports.sumOf = sumOf;
sum.test.js
const { sum, sumOf } = require('./sum');
describe('sum', () => {
it('calculates 1 + 2', () => {
expect(sum(1, 2)).toBe(3);
});
it('calculates all numbers', () => {
const array = [1, 2, 3, 4, 5];
expect(sumOf(array)).toBe(15);
});
});
- 두개의 테스트 케이스가 sum이라는 이름으로 분류
리펙토링
- 앞서 보았던 sumOf함수 내부의 forEach를 reducer를 사용해서 구현.
-> 만약 이렇듯 코드가 잘 리팩토링되어 작동하는지 검증하기가 매우 간편
sum.js
function sum(a, b) {
return a + b;
}
function sumOf(numbers) {
return numbers.reduce((acc, current) => acc + current, 0);
}
// 각각 내보내기
exports.sum = sum;
exports.sumOf = sumOf;
참조: https://learn-react-test.vlpt.us/#/01-javascript-testing
https://velog.io/@jonghunbok/%EC%9B%B9%EA%B0%9C%EB%B0%9C-TDD-%EC%9E%85%EB%AC%B8-Jest%EC%9D%98-Matchers-%EC%A0%95%EB%A6%AC