TDD, 테스트 자동화 기초 연습

라용·2022년 10월 10일
0

위코드 - 스터디로그

목록 보기
83/100

위코드에서 공부하며 정리한 내용입니다. (사진출처, 위코드)

1. 테스트 자동화 실습

Javascript 테스트 도구 Jest 를 활용합니다.

1-1. 유닛 테스트 실습

아래와 같은 계산기 프로그램 코드가 함수 단위로 나뉘어져 작성되었을 때,

// 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 같은 코드 파일을 찾아 자동으로 실행합니다.

1-2. 통합 테스트 실습

더하기 결과와 빼기 결과를 곱하는 과정을 통헤 테스트를 통합해보면,

// 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);
  });
});

이렇게 개별 단위 코드들을 모아 테스트를 구성하는 것을 상향식 통합 테스트라고 합니다.

2. 테스트 커버리지 확인

테스트 커버리지를 확인하는 명령어는 아래와 같습니다.

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를 사용하세요!");
    }
  });
});

3. E2E 테스트

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 를 실행해 테스트 결과를 확인합니다.

profile
Today I Learned

0개의 댓글