해당 글은 Node.js 교과서의 내용을 요약, 정리한 글입니다.
$npm i -D jset
테스팅 툴은 개발 시에만 사용하므로 -D옵션을 사용한다.
package.json에는 test라는 명령어를 등록해 둔다.
//package.json
{
"name":...
"version":...
...
"scrpits":{
"start":...
"test":"jest"
},
...
}
이 후 폴더 안에 middlewares.test.js를 만든다.
테스트용 파일은 파일명과 확장자 사이에 test나 spec을 넣으면 된다.
//middlewares.test.js
test('1+1',()=>{
expect(1+1).toEqual(2);
})
//결과
> nodejs@1.0.0 test
> jest
PASS testing/middlewares.test.js
√ 1+1 (2 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.822 s
Ran all test suites.
//middlewares.test.js
const { isLoggedIn,isNotLoggedIn} = require("./middlewares");
describe('isLoggedIn',()=>{
const res={
status:jest.fn(()=>res),
send:jest.fn(),
};
const next = jest.fn();
test('로그인되어 있으면 isLoggedIn이 next를 호출해야 함',()=>{
const req={
isAuthenticated:jest.fn(()=>true),
};
isLoggedIn(req,res,next);
expect(next).toBeCalledTimes(1);
});
test('로그인되어 있지 않으면 isLoggedIn이 에러를 응답해야 함',()=>{
const req={
isAuthenticated:jest.fn(()=>false),
};
isLoggedIn(req,res,next);
expect(res.status).toBeCalledWith(403);
expect(res.send).toBeCalledWith('로그인 필요');
});
});
여기서 describe함수는 test들을 그룹화 해주는 역할을 한다.
이렇게 작은 단위의 함수나 모듈이 의도된 대로 정확히 작동하는지 테스트하는 것을 유닛 테스트라고한다.
라우터의 한 부분을 다른 파일로 분리하여 테스트하는 것도 가능하다.
주의할 점은 async 함수는 await을 붙여야 컨트롤러가 실행 완료된 후 expect함수가 실행된다는 점이다.
테스트 코드에서의 객체는 실제 객체일 필요가 없다.
따라서 가짜 객체나 가짜 함수를 생성해서 넣어 주기도 하는데, 이를 모킹이라 한다.
jest는 모듈도 모킹할 수 있다.
jest.mock('../models/user');
const User = require('../models/user');
jest.mock에서는 모킹할 메서드에 mockReturnValue라는 메서드를 넣는다.이 메서드로 반환값을 지정할 수 있다.
전체 코드 중에서 어떤 부분이 테스트되고 어떤 부분이 테스트되지 않는지 확인하는 방법
//package.json
{
...
"scripts": {
"start":"nodemon app",
"test": "jest",
"coverage":"jest --coverage"
},
}
$npm run coverage
테스트 결과가 출력되고 추가적으로 표가 하나 더 출력된다.
% Stmts
//구문 비율
% Branch
//if문 등의 분기점 비율
% Funcs
//함수 비율
% Lines
코드 줄 수 비율
Uncovered Line
커버되지 않은 줄 위치
$npm i -D supertest
supertest를 사용하기 위해서는 app객체를 모듈로 만들어 분리해야 한다.
app.js파일에서 app객체를 모듈로 만든 후, server.js에서 불러와 listen한다.
server.js는 app의 포트 리스닝만 담당한다.
package.json을 상황에 맞게 수정한다.
"scripts": {
"start":"nodemon server",
"test": "jest",
"coverage":"jest --coverage"
},
통합 테스트에서는 데이터베이스 코드를 모킹하지 않는다. 따라서 테스트용 데이터베이스를 따로 만드는 것이 좋다.
//routes/auth.test.js
const request = require('supertest');
const { sequelize } = require('../models');
const app = require('../app');
beforeAll(async ()=>{
await sequilize.sync();
});
describe('POST /login',()=>{
test('로그인 수행', (done)=>{
request(app)
.post('/auth/login')
.send({
email: 'jinmin645@gmail.com',
password: '12345678',
})
.expect('Location','/')
.expect(302, done);
});
});
테스트를 실행하기 전에 실행하는 함수
자매품으로 afterAll, beforeEach, afterEach등이 있다.
$npm i -D artillery
$npm start
$npx artillery quick --count 100 -n 50 http://localhost:8001
localhost:8001에 빠르게 부하 테스트를 하는 방법.
--count는 가상 사용자 수를 의미한다.
-n옵션은 요청 횟수를 의미한다.
request latency가 중요한데, 보통 median과 p95값의 차이가 크지 않으면 좋다.
//loadtest.json
{
"config":{
"target":"http://localhost:8001",
"phases":[
{
"duration":60,
"arrivalRate":30
}
]
},
"scenarios":[{
"flow":[
{
"get":{
"url":"/"
}
},{
"post":{
"url":"/auth/login",
"json":{
"email":"jinmin645@gmail.com",
"password":"12345678"
}
}
},{"get":{
"url":"/"
}
}
]
}]
}
target: 목표 서버
phases.duration: 60초 동안
phases.arrivalRate: 매 초 30명의 사용자
scenarios대로 동작한다.