단위 테스트 (유닛 테스트)
두가지로 나뉘어서 작동한다.
test runner : 테스트를 실행 후 결과 생성 (mocha)
assertion : 테스트 조건, 비교를 통한 테스트 로직 (chai, expect, better-assert)
라이브러리를 따로따로 생성했었다.
요즘에는 별도로 구분하지 않아도 jest를 사용하면 간편하다.
Jest
Js 환경에서 testing할 수 있는 프레임워크 이다.
zero config 복잡한 설정을 하지 않아도 간단하게 테스트 할 수 있음.
테스트가 어떻게 실패했는 지 정확하게 볼 수 있다.
jest 설치
npm install jest --global
터미널에 jest --init
package.json에 test 될 수 있게 > yes
타입스크립트 사용할건지? > yes or no
test 환경 설정 / node or 브라우저 > node
jest가 커버리지 리포트를 하길 원하는지? > yes
어떤 툴을 사용할건지? babel or v8 > v8
자동적으로 매번 실행할 때 마다 인스턴스나 mock call을 매번 청소할건지? yes
이렇게 하면, jest.config.js가 생성이 된다.
package.json에 test 환경을 실행할 수 있다.
다른 개발자들도 jest 환경을 들어올 수 있도록, npm install --save-dev jest 해준다.
jest.config.js 에서 collectCoverage : 커버리지 on off 하는 것
expect(received).toBe(expected) // Object.is equality
Expected: 3
Received: -1
3 | test("", () => {
4 | // 테스트 코드 작성
> 5 | expect(add(1, 2)).toBe(3);
| ^
6 | });
7 |
8 | //테스트에 관한 타입 정보가 없음 @types/jest 설치.
실행할 때마다 자동으로 실행하고 싶다면,
"test": "jest --watchAll"
이렇게, package.json에서 정해주면 된다
jest --watch <- 깃을 사용한다면, 커밋 이후 수정되는 코드들만 테스팅
https://jestjs.io/docs/using-matchers
공식문서 유심히 살펴보기
비교 연산, 참 거짓 같은 것도 toEqual 같은 것으로 확인이 가능하다.
계산기 코드, 테스트 파일 작성하기
//관련있는 테스트를 그룹으로 묶을 수 있음!
//beforeEach <- 하나하나씩 테스트 하기 전에 먼저 수행되어야 할 함수들을 지정해 줌!
//afterEach <- 하나하나 테스트 한 후에 수행되어야 할 함수
//여기서는, class를 선언하는 것을 먼저 수행해주어야 함. 중요한 점은 각각의 테스트들은 독립적으로 수행되어야 한다는 것.
에러 테스트 하기
it("add should throw an error if value is greater than 100", () => {
expect(() => {
cal.add(101);
}).toThrow("Value can not be greater than 100");
});
이렇게 expect에 error를 뿜는 코드를 작성하고, toThrow에 error 메시지를 준다.
비동기 테스트 하기
describe("Async", () => {
it("async", () => {
fetchProduct().then((item) => {
expect(item).toEqual({
item: "poop",
price: 200,
});
});
});
});
이렇게 test 를 하면, 비동기 코드는 promise는 fetchProduct를 호출해놓고, then이 어떤 행동을 했는 지 관계없이 it을 실행하고 끝난다.
우리가 원하는 것은, jest가 promise 결과가 나와서 검증이 나올 때 까지 모든 행동을 다 보아야 한다.
jest --verbose : 자세한 설명을 console 창에서 볼 수 있음.
https://jestjs.io/docs/asynchronous
Mock에 대해
function check(predicate, onSuccess, onFail) {
if (predicate()) {
onSuccess('yes');
} else {
onFail('no');
}
}
module.exports = check;
이렇게 check 함수가 있을 때, predicate 함수가 동작되면 onSuccess 함수를 호출하고, 아니라면 onFail 함수를 호출하라는 mock을 이용한 Test 코드를 작성해야 한다.
const check = require("../check");
describe("check", () => {
let onSuccess;
let onFail;
beforeEach(() => {
onSuccess = jest.fn();
onFail = jest.fn();
});
it("should call onSuccess when predicate is true", () => {
check(() => true, onSuccess, onFail);
expect(onSuccess.mock.calls.length).toBe(1);
expect(onSuccess).toHaveBeenCalledTimes(1);
expect(onSuccess.mock.calls[0][0]).toBe("yes");
expect(onSuccess).toHaveBeenCalledWith("yes");
expect(onFail.mock.calls.length).toBe(0);
expect(onFail).toHaveBeenCalledTimes(0);
});
it("should call onFail when predicate is true", () => {
check(() => false, onSuccess, onFail);
expect(onFail).toHaveBeenCalledTimes(1);
expect(onFail).toHaveBeenCalledWith("no");
expect(onSuccess).toHaveBeenCalledTimes(0);
});
});
이렇게, 일단 처음에 onSuccess, onFail을 선언부터 하고, 이것을 mock 함수로 만들어준다. jest.fn() 으로 하면 됨
그 전에 사용했던 beforeEach() 로 시작 전에 선언한다.
그리고 check(() => true, onSuccess, onFail)로 인자값을 넣어준다. 일단 predicate는 true가 되는 것이다.!
이렇게 되면 onSuccess는 1번 실행이 되고 onFail은 실행이 안되어야 하기 때문에 이것을 Test코드로 작성해줘야 한다.
뭔가 들으면 들을 수록 테스트 코드를 짤 때 설계가 중요하다.
'React' 카테고리의 다른 글
[react] TDD (0) | 2024.06.18 |
---|---|
[react] TDD - 좋은 테스트 원칙 (0) | 2024.06.18 |
[react] TDD - 테스트란? (1) | 2024.06.16 |
react-native mac에서 android 설정할 때 Error (0) | 2024.04.25 |
react.js - Ant Design / styled-components (0) | 2023.02.21 |