위코드에서 공부하며 정리한 내용입니다. (사진출처, 위코드)
Javascript 테스트 도구 Jest 를 활용합니다.
아래와 같은 계산기 프로그램 코드가 함수 단위로 나뉘어져 작성되었을 때,
// calculate.js
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
function multiple(a, b) {
return a * b;
}
function divide(a, b) {
return a / b;
}
module.exports = { add, subtract, multiple, divide }
단위 테스트 코드를 작성해보면 아래와 같습니다.
(테스트 파일은 calculate.js 옆 calculate.test.js 파일로 생성)
// calculate.test.js
const { add, subtract, multiple, divide } = require('./calculate');
describe('calculate unit test', () => {
describe("add", () => {
test("add(1,2)는 3이 되어야합니다.", () => {
expect(add(1, 2)).toBe(3);
});
});
describe("subtract", () => {
test("subtract(2,1)는 1이 되어야합니다.", () => {
expect(subtract(2, 1)).toBe(1);
});
});
describe("multiple", () => {
test("multiple(3, 4)는 12가 되어야합니다.", () => {
expect(multiple(3, 4)).toBe(12);
});
});
describe("divide", () => {
test("divide(10, 2)는 5가 되어야합니다.", () => {
expect(divide(10, 2)).toBe(5);
});
});
});
테스트 코드는 describe 와 test (callback)부분으로 나뉘고 test 부분에 다시 describe 와 test 를 선언할 수 있습니다. 그리고 expect 를 통해 정상 수행여부를 확인합니다. (하나의 테스트에 여러 개의 expect 들어갈 수 있음)
이제 테스트 코드 실행을 위해 jest 를 설치하고 실행합니다.
$ npm i -D jest // jest 설치
$ npx jest # jest 실행
jest 프로그램은 .test.js 나 spec.js 같은 코드 파일을 찾아 자동으로 실행합니다.
더하기 결과와 빼기 결과를 곱하는 과정을 통헤 테스트를 통합해보면,
// calculate.test.js
const { add, subtract, multiple, divide } = require('./calculate');
...기존 unit test
/// 통합 테스트 추가
describe("calculate integration test", () => {
test("add(1, 3)과 subtract(4, 2)를 multiple한 결과는 8입니다.", () => {
const addResult = add(1, 3);
expect(addResult).toBe(4);
const subtractResult = subtract(4, 2);
expect(subtractResult).toBe(2);
expect(multiple(addResult, subtractResult)).toBe(8);
});
});
이렇게 개별 단위 코드들을 모아 테스트를 구성하는 것을 상향식 통합 테스트라고 합니다.
테스트 커버리지를 확인하는 명령어는 아래와 같습니다.
npx jest --coverage
모든 구문과 분기점들을 100% 커버하고 있다면 이렇게 나옵니다. 여기서 add 함수 코드를 추가해보면,
function add(a, b) {
/// 추가된 부분
if (b < 0) {
throw new Error("b가 0보다 작습니다. subtract를 사용하세요!");
}
/// ---------
return a + b;
}
b가 0보다 작을 때 함수 기능을 종료하게 합니다. 다시 jset 명령어를 입력하면
npx jest --coverage
변경된 커버리지를 확인할 수 있습니다. 우측 Uncovered Line 에서는 특정 위치를 알려주기도 합니다.
아래 처럼 add 테스트를 추가해서 커버리지를 다시 높일 수 있습니다.
(jest 는 기본적으로 .test.js, .spec.js 파일들만 테스트하고 커버리지 산정은 테스트 파일 내 import 된 코드만 이용해 계산함)
describe("add", () => {
test("add(1, 2)는 3이 되어야합니다.", () => {
expect(add(1, 2)).toBe(3);
});
// 아래 테스트 추가
test("add(1, -1)은 에러를 던집니다.", () => {
try {
add(1, -1);
} catch (err) {
expect(err).toBeInstanceOf(Error)
expect(err).toHaveProperty("message", "b가 0보다 작습니다. subtract를 사용하세요!");
}
});
});
E2E 테스트는 실제 환경과 동일하게 구성해 사용자 요청부터 시작해 결과를 받는 것까지 모두 테스트합니다. 서버 모듈 프레임워크 express 를 사용해 계산기 프로그램을 테스트 한다면,
// app.js
const express = require("express"); // express 모듈은 npm i express로 설치
const { add, subtract, multiple } = require("./calculate");
const app = express();
// 쿼리 스트링으로 받는 a와 b를 숫자로 바꾸어서 다음 컨트롤러로 넘기는 미들웨어 입니다.
app.use((req, res, next) => {
const { a, b } = req.query;
req.num = {
a: Number(a),
b: Number(b),
};
next();
});
app.get("/add", (req, res) => {
const { a, b } = req.num;
const result = add(a, b);
res.json({ result });
});
app.get("/subtract", (req, res) => {
const { a, b } = req.num;
const result = subtract(a, b);
res.json({ result });
});
app.get("/multiple", (req, res) => {
const { a, b } = req.num;
const result = multiple(a, b);
res.json({ result });
});
app.get("/divide", (req, res) => {
const { a, b } = req.num;
const result = divide(a, b);
res.json({ result });
});
module.exports = app;
그리고 나서 server.js 와 server.spec.js 를 만들어 아래 코드를 넣습니다. (설치하지 않은 모듈이 있다면 설치)
// server.js
const http = require("http"); // http 모듈은 node에 내장되어있으므로 설치 x
const app = require("./app");
http.createServer(app).listen(10010);
// server.spec.js
const http = require("http");
const fetch = require("node-fetch-commonjs"); // npm i node-fetch-commonjs
const app = require("./app");
describe("E2E Test", () => {
let server;
beforeEach(() => {
// 테스트 케이스들이 독립된 환경에서 테스트할 수 있게 개별적으로 listen합니다.
server = http.createServer(app).listen(10010);
});
afterEach(() => {
// 각 테스트가 끝난후 서버를 종료시킵니다.
server.close();
// 가비지 컬렉터에서 http server 객체를 메모리에서 해제하게 만듭니다.
server = null;
});
test("사용자가 a에 3, b에 4를 담아 add로 get 요청합니다.", async () => {
const resBody = await fetch("http://localhost:10010/add?a=3&b=4").then(
(res) => res.json()
);
expect(resBody.result).toBe(7);
});
test("사용자가 a에 6, b에 2를 담아 subtract로 get 요청합니다.", async () => {
const resBody = await fetch("http://localhost:10010/subtract?a=6&b=2").then(
(res) => res.json()
);
expect(resBody.result).toBe(4);
});
});
이제 npx jest 를 실행해 테스트 결과를 확인합니다.