단위 테스트 (Unit Test)
: 컴퓨터 프로그래밍에서 소스 코드의 특정 모듈이 의도된 대로 정확히 검증하는 절차
: 모든 함수와 메소드에 대한 테스트 케이스를 작성하는 절차
: 유닛 테스트 메서드를 따로 작성하여 전체 프로그램을 실행하지 않고 특정 루틴을 테스트
- 유닛테스트를 하는 이유
: 버그를 줄이고 코드 퀄리티를 높이기 위함
: 의존성이 있는 다른 클래스들에서 버그가 나는 것을 방지하지 위함
- Stub
: 테스트 중인 모듈이 호출하는 다른 소프트웨어 구성요소를 일시적으로 대체하는 소프트웨어 구성요소
: 유닛 A를 테스트할 때 유닛 A가 호출하는 유닛 B 대신 작성하는 가짜 객체 Stub
ex) 메일 보내기 모듈을 테스트 할 때 구현되지 않은 수신 확인 모듈을 대체하여 Stub 작성
- Stub를 사용하는 이유
: 구현되지 않은 함수나 라이브러리에서 제공하는 함수를 사용할 때
: 함수가 반환하는 값을 임의로 생성하고 싶을때 (예외처리를 위함)
: 복잡한 논리 흐름을 가지는 경우 테스트를 단순화 하고 싶을때
: 의존성을 가지는 유닛의 응답을 모사하여 독립적인 시험 수행을 하고자 할 때
통합 테스트 (Integration Test)
: 모듈을 통합하는 과정에서 모듈간의 호환성을 확인하기 위해 수행되는 테스트
: 독립적인 기능의 테스트가 아닌 웹 페이지로 부터 API를 호출하여 올바르게 동작하는지 확인
단위 테스트를 수행하는 방법
- 직접 함수 작성
: 작성한 모듈을 호출하여 결과를 받아내는 함수 (stub)를 작성
: 만든 Stub을 실행하여 결과 확인
- 유닛테스트 라이브러리 사용
: jest
: mocha
: chai
: sinon (mocking)
jest를 통한 node JS 모듈 테스트를 위한 stub 작성
- 테스트를 수행할 모듈 작성 (sum.js)
function sum(a, b) {
return a + b;
}
module.exports = sum;
- stub 작성 (sum.test.js)
test('two plus two is four', () => {
expect(sum(2, 2)).toBe(4);
});
※ test(name, fn, timeout)
: name = 테스트에 대한 설명
: fn = 함수
: timeout = 응답제한 시간
※ expect(value)
: .toBe와 같은 mather와 함께 사용
: value로는 함수를 넣어서 테스트
※ .toBe(value)
: 기대하는 값
- describe 작성
const myBeverage = {
delicious: true,
sour: false,
};
describe('my beverage', () => {
test('is delicious', () => {
expect(myBeverage.delicious).toBeTruthy();
});
test('is not sour', () => {
expect(myBeverage.sour).toBeFalsy();
});
});
※ describe(name, fn)
: 서로 관련있는 테스트를 묶음
: name = 테스트 그룹의 이름
: fn = 테스트 함수들의 묶음
- mocking
function forEach(items, callback) {
for (let index = 0; index < items.length; index++) {
callback(items[index]);
}
}
※ mocking
: 임시의 테스트용 함수를 만드는 것
- mocking 테스트용 모듈 (forEach.test.js)
forEach = require('./forEach');
test('forEach()', () => {
const mockCallback = jest.fn(x => 42 + x);
forEach([0, 1], mockCallback);
// The mock function is called twice
// same as expect(mockCallback).toBeCalledTimes(2);
expect(mockCallback.mock.calls.length).toBe(2);
// The first argument of the first call to the function was 0
expect(mockCallback.mock.calls[0][0]).toBe(0);
// The first argument of the second call to the function was 1
expect(mockCallback.mock.calls[1][0]).toBe(1);
// The return value of the first call to the function was 42
expect(mockCallback.mock.results[0].value).toBe(42);
})
※ jest.fn(implemetation)
: 모킹할 내용
: 위 예제에서는 임의로 작성한 forEach 함수에 x => 42 + x 라는 값을 넣어 호출한 것
※ mockFn.mock.calls
: i번째 호출에서의 j번째 인자를 갖는 배열
※ mockFn.mock.results
: type과 value라는 객체를 요소로 하는 배열
※ mockFn.mockName(value)
: value = mock 함수의 이름
: jest.fn() 대신 이름을 붙일때 사용
const mock = jest.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43
※ mockFn.mockReturnValue(value)
: mock 함수의 리턴값을 지정
- 모듈 mocking (banana.js)
// banana.js
module.exports = () => 'banana';
// __tests__/test.js
jest.mock('../banana');
const banana = require('../banana'); // banana will be explicitly mocked.
banana(); // will return 'undefined' because the function is auto-mocked.
: jest.mock에 모킹할 모듈의 이름을 넘김
- 모킹한 모듈 호출
jest.mock('../models/user');
const User = require('../models/user');
const {addFollowing} = require('./user');
describe('addFollowing', ()=>{
const req = {
user : {
id : 1,
},
params : {
id : 2,
}
};
const res = {
status : jest.fn(()=>res),
send : jest.fn(),
};
const next = jest.fn();
test('사용자를 찾아 팔로잉을 추가하고 success를 응답해야 함', async()=>{
User.findOne.mockReturnValue({
addFollowing(id){
return Promise.resolve(true);
}
});
await addFollowing(req, res, next);
expect(res.send).toBeCalledWith('success');
});
test('사용자를 못 찾으면 res.status(404).send(no user)를 호출함', async()=>{
User.findOne.mockReturnValue(null);
await addFollowing(req, res, next);
expect(res.status).toBeCalledWith(404);
expect(res.send).toBeCalledWith('no user');
});
test('DB에서 에러가 발생하면 next(error)를 호출함', async()=>{
const error = '테스트용 에러';
User.findOne.mockReturnValue(Promise.reject(error));
await addFollowing(req, res, next);
expect(next).toBeCalledWith(error);
});
})
jest를 통한 node JS 모듈 테스트
- 프로젝트에 jest 설치
: npm install -D jest
{
...
"scripts": {
"start": "nodemon app",
"test": "jest"
},
...
}
- test 코드 실행을 위한 스크립트 추가
: package.json의 scripts에 test 추가
- 테스트 실행
: npm test
: 자동으로 파일명에 test나 spec이 들어간 파일들을 모두 찾아서 실행
Refference
단위시험을 여행하는 테스터를 위한 테스트 스텁의 정의와 사용법
컴퓨터 프로그래머나 테스터들이라면 한번쯤 스텁(Stub)이라는 얘기를 들어본 적 있을 것이다. 위키에서는...
blog.naver.com
그래서 유닛테스트(Unit Test)가 뭔가요?
소프트웨어 업계에 종사하거나 개발을 많이 해봤다면 유닛테스트에 대해 종종 들었을 것이다. 업계에 종사하고있다면 실제로 유닛테스트를 매일 작성하고 있을수도 있다. 유닛테스트는 뭘까?
imasoftwareengineer.tistory.com
[TDD] 단위 테스트(Unit Test) 작성의 필요성 (1/3)
1. 단위 테스트 vs 통합 테스트 차이 [ 단위 테스트(Unit Test) ] 단위 테스트(Unit Test)는 하나의 모듈을 기준으로 독립적으로 진행되는 가장 작은 단위의 테스트이다. 여기서 모듈은 애플리케이션에
mangkyu.tistory.com
nodejs 테스트 도구와 방법론 (테스트의 중요성, 전략, mocha, chai, sinon, istanbul, 유용한 팁)
1. 테스트를 왜 해야하는가? 테스트를 안하는 개발자는 없다. 코드 작성 후 서버를 뛰워서 api url을 호출해서 응답값을 확인해보고, UI에서 버튼을 눌러보고 하는 것도 모두 테스트이다. 그러나 여
sjh836.tistory.com
[Node.JS] 개발 후 테스트 하기 - 유닛 테스트
개발을 마친 후 배포하기 전에는 반드시 테스트를 해야합니다. 노드로 만든 서버를 테스트를 할 때는 jest라는 패키지를 사용합니다.jest는 페이스북에서 만든 테스트 패키지입니다.test를 입력
velog.io
'Programming > NodeJS' 카테고리의 다른 글
클러스터링을 이용한 멀티쓰레드 IPC (0) | 2022.08.31 |
---|---|
NodeJS memory leak 추적하는 방법 (메모리를 낭비하는 함수 추적) (0) | 2022.08.26 |
NodeJS에서 로깅하기 (0) | 2022.08.13 |
NodeJS의 메모리 누수 확인 방법 (0) | 2022.08.13 |
NodeJS의 메모리 관리 방법 (V8 엔진과 가비지 컬렉션) (0) | 2022.08.13 |