TIL - 38 : TDD - Unit Test
in Study Log on Today I learned

TDD - Unit Test
- Test Runner - 테스트를 실행 후 결과 생성
- Mocha
- Assertion - 테스트 조건, 비교를 통한 테스트 로직
- Chai
- expect.js
- better-assert
Jest를 이용하면 따로 테스트를 하지 않아도 할 수 있어 좋음
npm이 없다면
npm init -ynpm i jest-dev 옵션jest --initJest 홈페이지 참고
파일명.test.js: add라는 파일에 한해서 단위 테스트를 작성하겠다.
const add = require('../add.js'); // node에서는 import가 require
test('테스트이름', () => {
// 테스트 코드 작성
});
- jest 를 실행할때 옵셥을 줄 수 있다.
"test": "jest --watchAll"파일이 변경될때마다 테스트 실행"test": "jest --watch"하나의 파일만 실행
- Object를 비교하고 싶다면
.toEqual사용
test('add', () => { // 'add'는 테스트 이름
// 테스트 코드 작성
expect(add(3, 5)).toBe(8); // add 라는 함수에 3,5를 넣으면 정확하게 8이 나와야한다.
});
- test : 테스트
- expect() : 테스트를 작성할 때 종종 값이 특정 조건을 충족하는지 확인, 예상하다.
- toBe() : 정확하게 나와야 하는 값
describe('Calculator', () => {
// 관련된것을 그룹으로 묶음
it('init with 0', () => {
const cal = new Calculator();
expect(cal.value).toBe(0);
}); //it은 caculator 임
it('set test', () => {
const cal = new Calculator();
cal.set(9);
expect(cal.value).toBe(9);
});
});
- describe : 여러 관련된 것을 그룹화 해서 테스트
it : 테스트 이름을 가르키는 네이밍
- 위와 같이 cal을 만들어 주는 중복 함수는 전역에 한번 선언 할 수도 있지만,
각각의 테스트는 따로 해주는것이 좋음 - 그렇지만 코드의 중복을 막아야 하기에 다음과 같이 작성
const cal;
beforeEach(()=>{
cal = new Calculator();
})
- beforeEach() : 테스트 코드를 실행 하기 전에 수행
- afterEach() : 테스트 코드를 실행 한 이후에 수행
- beforeAll() : 모든 테스트 코드 전에 한번 실행
- afterAll() : 모든 테스트 코드 후에 한번 실행
Error Test
- coverage 를 보면 커버하지 않은 라인을 확인할 수 있음
add(num) {
if (sum > 100) {
throw new Error('100을 넘을 수 없습니다.');
}
this.value = sum;
}
- 이러한 에러를 설정해 놓았다면
it('addError', () => {
expect(() => {
cal.add(150);
}).toThrow('100을 넘을 수 없습니다.');
});
- 이렇게 에러 메세지도 확인이 가능함
Async Test
function fetchProduct(error) {
if (error === 'error') {
return Promise.reject('network error');
}
return Promise.resolve({ item: 'Milk', price: 200 });
}
- 이러한 비동기 코드가 있으면
describe('Async', () => {
it('asyc', () => {
fetchProduct().then((item) => { // 아이템을 리턴한다면
expect(item).toEqual({ item: 'Milk', price: 200 });
// 아이템은 이 오브젝트와 동일한지 검사
});
});
});
- 하지만 이렇게하면 비동기 값이 들어오든 말든 바로 이상 없으면 PASS
- 이현상을 없애주기 위해서 따로 done이라는 인자를 받아와서 마지막에 호출
- 간단히 return으로도 가능
describe('Async', () => {
it('async - done', (done) => { // done을 인자로 받고
fetchProduct().then((item) => {
expect(item).toEqual({ item: 'Milk', price: 200 });
done(); // done을 마지막에 호출
});
});
//or
it('async - return', () => {
return fetchProduct().then((item) => {
expect(item).toEqual({ item: 'Milk', price: 200 });
});
});
});
// await 방식
it('async - await', async () => {
const product = await fetchProduct();
expect(product).toEqual({ item: 'Milk', price: 200 });
});
하지만 done 방식은 느리기때문에 더빠르고 코드도 깔끔한 return 방식 추천
함수는 Mock 함수를 이용하면 쉽게 테스트 가능
- 네트워크 상태의 의존하는 코드는 좋지 않음, 이것도 Mock을 이용
- mock은 흉내 stub은 진짜 같은 진짜 대체 코드
- 네트워크를 하는게 있다면 따로 클라이언트를 만드는것이 좋다.