TDD 001: 유닛테스트 작성하기 - 함수

Raymond Yoo·2022년 1월 15일
0

TDD

목록 보기
1/6
post-thumbnail
post-custom-banner

자바스크립트에서 테스트 코드 작성하는 방법을 알아보자.

소스코드 링크


기본적인 프로젝트 설정

npm init
git init
git branch -M main

명령어를 이용해서 nodejs 프로젝트를 초기화한하고
.gitignore 파일을 생성해서 node_modules/ 를 추가한다.
이후에

  1. 테스트 라이브러리 mocha
  2. assertion 라이브러리 chai

두 가지를 development dependency로 설치한다.

npm i -D mocha chai

이제 package.json 파일에 다음과 같은 영역이 생겨난다.

  "dependencies": {
  },
  "devDependencies": {
    "chai": "^4.3.4",
    "mocha": "^9.1.3",
  }

여기에 테스트를 위한 스크립트 test 를 추가한다.

  "scripts": {
    "test": "mocha"
  },

워크스페이스 루트에 src/, test/ 두 개의 디렉토리를 생성한다.

src/ 디렉토리에 app.js 파일을 만들고
test/ 디렉토리에 app.js 파일을 만든다.
테스트 코드를 작성하는 파일명으로 app.test.js, app.spec.js 등등이 가능하지만
개인적으로는 이미 개별적인 폴더를 생성해서 프로덕션 코드와 테스트 코드를 분리했으므로
테스트 코드의 파일명을 본래 코드의 파일명과 동일하게 하는 것이 좋다고 생각한다.

여기까지 세팅이 제대로 되었는지 확인하기 위해 터미널에서 테스트를 실행해본다.

npm test

다음과 같은 화면이 나타난다.
아직 테스트 코드를 작성하지 않았기 때문에 0 passing 이라고 나온다.

TDD 001 image 01


테스트 코드 1

여기서는 간단한 예시로
2개의 숫자를 파라미터로 받아서 더한 값을 리턴하는 함수 add 를 만든다.

// src/app.js
function add(a, b) {
  return a + b;
}

module.exports = {
  add,
};

그리고 방금 작성한 src/app.js 를 테스트하는 코드를 test/app.js 에 작성한다.

// test/app.js
const expect = require("chai").expect;
const app = require("../src/app");

describe("functions 'add' in App", function () {
  it("should add 2 numbers together", function () {
    const result = app.add(2, 3);
    expect(result).to.be.equal(5);
  });
});

이제 터미널에서 npm test 명령어로 다시 테스트를 실행하면 다음과 같은 화면이 나타난다.

TDD 001 image 02

방금 작성한 첫번째 테스트 코드가 적상적으로 실행됐다는 것을 확인할 수 있다.


테스트 코드 2 - 테스트 실패와 실제 코드 내 오류 발견

이번엔 하나의 파라미터만 사용해서 add 함수를 호출하는 경우의 테스트를 실행해보자.

// test/app.js
...
describe("functions 'add' in App", function () {
  ...
  it("should be able to hanlde 1 number", function () {
    const result = app.add(2);
    expect(result).to.be.equal(2);
  });
});

그리고 터미널에서 테스트를 실행해보면 다음과 같이 실패한다.

TDD 001 image 03

	const result = app.add(2);

이 라인에서 result 에 NaN 이 들어가있고, 이 값이 2인지 확인하고 있으니 테스트 코드가 실패했다.
테스트 코드 작성을 통해서 add 함수의 잘못되었다는 것을 확인했다. 고심 끝에 다음과 같이 고치기로 결정한다.

  • add 함수는 기본적으로 두 개의 파라미터를 받도록 되어 있으므로
    파라미터에 기본값(default value) 0 을 추가한다.

그러므로 src/app.js 파일을 다음과 같이 수정했다.

function add(a, b = 0) {
  return a + b;
}
...

다시 테스트 코드를 실행하면 다음과 같이 모든 테스트 코드가 성공한다.

TDD 001 image 04


테스트 코드 3

이번에는 아무런 파라미터 없이 add 함수를 호출해보기로 한다.

// test/app.js
describe("functions 'add' in App", function () {
  ...
  
  it("should be able to handle 0 number", function () {
    const result = app.add();
    expect(result).to.be.equal(0);
  });
});

실패한다. 이유는 테스트 코드 2가 처음에 실패한 이유와 비슷하게 NaN !== 0 이기 때문이다.
add 함수를 다음과 같은 요구조건을 만족하도록 수정한다.

  • add 함수는 기본적으로 두 개의 파라미터를 받도록 되어 있다.
    이 함수를 사용하는 곳에서 아무런 파라미터도 입력하지 않으면 기본값으로 0을 대입한다.

add 함수의 첫번째 파라미터 a 에도 기본값 0 을 추가한다.

// src/app.js
function add(a = 0, b = 0) {
  return a + b;
}

이제 다시 테스트를 실행하면 다음과 같이 성공한다.

TDD 001 image 05


테스트 코드 4

이번에는 add 함수에 숫자가 아닌 값을 파라미터로 주어서 호출하려고 해보자.

// test/app.js
describe("functions 'add' in App", function () {
  ...
  
  it("should return 0 if either argument is not a number", function () {
    const result = app.add(2, "test");
    expect(result).to.be.equal(0);
  });
});

테스트 스크립트는 다음과 같은 오류로 실패한다.

TDD 001 image 06

자바스크립트의 언어적 특징으로 인해서 숫자와 문자열에 대한 + 연산은 concatenation 이 된다.
이 문제를 해결하기 위해서 add 함수를 다음과 같이 고치기로 결정했다.

  • add 함수의 파라미터 둘 중에 하나라도 숫자('number') 타입이 아닌 경우에는
    곧바로 0 을 리턴한다.

방금 새롭게 정한 원칙을 따라서 add 함수를 다시 작성한다.

// src/app.js
function add(a = 0, b = 0) {
  if (typeof a !== "number" || typeof b !== "number") {
    return 0;
  }
  return a + b;
}
...

다시 테스트 코드를 실행하면 100% 성공한다.

TDD 001 image 07

새로운 함수 추가

// src/app.js
...
function sub(a = 0, b = 0) {
  if (typeof a !== "number" || typeof b !== "number") {
    return 0;
  }
  return a - b;
}

module.exports = {
  add,
  sub
};
// test/app.js
...
describe("function 'sub' in App", function () {
  it("should sub 2nd number from 1st nubmer", function () {
    const result = app.sub(1, 4);
    assert.equal(result, -3);
  });

  it("should be able to handle 1 number", function () {
    const result = app.sub(5);
    assert.equal(result, 5);
  });

  it("should be able to handle 0 number", function () {
    const result = app.sub();
    assert.equal(result, 0);
  });

  it("should return 0 if either argument is not a number", function () {
    const result = app.sub(1, "test");
    assert.equal(result, 0);
  });
});
...

이렇게 작성한 후에 테스트 스크립트를 실행하면 다음과 같은 화면이 나타난다.

TDD 001 image 07

profile
세상에 도움이 되고, 동료에게 도움이 되고, 나에게 도움이 되는 코드를 만들고 싶습니다.
post-custom-banner

0개의 댓글