BDD는 테스트(test), 문서(documentation), 예시(example)를 한데 모아놓은 개념입니다.
먼저, 코드가 무슨 일을 하는지 상상한 후 이를 자연어로 표현해야 합니다.
이때, 만들어진 산출물을 BDD에선 명세서(specification) 또는 짧게 줄여 스펙(spec) 이라고 부릅니다. 명세서엔 아래와 같이 유스 케이스에 대한 자세한 설명과 테스트가 담겨있습니다.
명세서는 실행 가능합니다. 명세서를 실행하면 it 블록 안의 테스트가 실행됩니다.
<script>
// 거듭제곱 함수
describe("pow", function() {
it("주어진 숫자의 n 제곱", function() {
assert.equal(pow(2, 3), 8);
});
});
</script>
describe("title", function() { ... })
구현하고자 하는 기능에 대한 설명이 들어갑니다. 우리 예시에선 함수 pow가 어떤 동작을 하는지에 대한 설명이 들어갈 겁니다. it 블록을 한데 모아주는 역할도 합니다.
it("유스 케이스 설명", function() { ... })
it의 첫 번째 인수엔 특정 유스 케이스에 대한 설명이 들어갑니다. 이 설명은 누구나 읽을 수 있고 이해할 수 있는 자연어로 적어줍니다. 두 번째 인수엔 유스 케이스 테스트 함수가 들어갑니다.
assert.equal(value1, value2)
기능을 제대로 구현했다면 it 블록 내의 코드 assert.equal(value1, value2)이 에러 없이 실행됩니다.
함수 assert.*는 pow가 예상한 대로 동작하는지 확인해줍니다.
위 예시에선 assert.equal이 사용되었는데, 이 함수는 인수끼리 동등 비교했을 때 다르다고 판단되면 에러를 반환합니다. 예시에선 pow(2, 3)의 결괏값과 8을 비교합니다.
총 2개의 라이브러리를 사용해 테스트를 진행해보겠습니다.
세 라이브러리 모두, 브라우저나 서버 사이드 환경을 가리지 않고 사용 가능합니다. 여기선 브라우저 환경을 가정하고 사용해 보겠습니다.
test.js
<script>
// 거듭제곱 함수
describe("pow", function() {
it("주어진 숫자의 n 제곱", function() {
assert.equal(pow(2, 3), 8);
});
});
</script>
HTML
<!DOCTYPE html>
<html>
<head>
<!-- 결과 출력에 사용되는 mocha css를 불러옵니다. -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mocha/3.2.0/mocha.css">
<!-- Mocha 프레임워크 코드를 불러옵니다. -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/3.2.0/mocha.js"></script>
<script>
mocha.setup('bdd'); // 기본 셋업
</script>
<!-- chai를 불러옵니다 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.5.0/chai.js"></script>
<script>
// chai의 다양한 기능 중, assert를 전역에 선언합니다.
let assert = chai.assert;
</script>
</head>
<body>
<script>
function pow(x, n) {
return 8; // 항상 8을 반환하도록 해놨습니다.
}
</script>
<!-- 테스트(describe, it...)가 있는 스크립트를 불러옵니다. -->
<script src="test.js"></script>
<!-- 테스트 결과를 id가 "mocha"인 요소에 출력하도록 합니다.-->
<div id="mocha"></div>
<!-- 테스트를 실행합니다! -->
<script>
mocha.run();
</script>
</body>
</html>
<head> – 테스트에 필요한 서드파티 라이브러리와 스타일을 불러옴
<script> – 테스트할 함수(pow)의 코드가 들어감
테스트 – describe("pow", ...)를 외부 스크립트(test.js)에서 불러옴
HTML 요소 \<div id="mocha"> – Mocha 실행 결과가 출력됨
mocha.run() – 테스트를 실행시켜주는 명령어
지금은 함수 pow가 항상 8을 반환하도록 해놨기 때문에 테스트를 통과합니다.
스펙에 테스트를 추가하는 방법
<script>
describe("pow", function() {
it("2를 세 번 곱하면 8입니다.", function() {
assert.equal(pow(2, 3), 8);
});
it("3을 네 번 곱하면 81입니다.", function() {
assert.equal(pow(3, 4), 81);
});
});
</script>
함수는 항상 8을 반환하고 있기 때문에 두번째 테스트를 통과할 수 없습니다.
제대로 작동시키기 위해선 코드를 아래와 같이 작성해야 합니다.
<script>
function pow(x, n) {
let result = 1;
for (let i = 0; i < n; i++) {
result *= x;
}
return result;
}
</script>
<script>
describe("test", function() {
before(() => alert("테스트를 시작합니다 - 테스트가 시작되기 전"));
after(() => alert("테스트를 종료합니다 - 테스트가 종료된 후"));
beforeEach(() => alert("단일 테스트를 시작합니다 - 각 테스트 시작 전"));
afterEach(() => alert("단일 테스트를 종료합니다 - 각 테스트 종료 후"));
it('test 1', () => alert(1));
it('test 2', () => alert(2));
});
</script>
실행 결과
assert.isNaN - NaN인지 아닌지를 확인해줍니다.
assert.equal(value1, value2) – value1과 value2의 동등성을 확인합니다.
(value1 == value2)
assert.strictEqual(value1, value2) – value1과 value2의 일치성을 확인합니다.
(value1 === value2)
assert.notEqual, assert.notStrictEqual – 비 동등성, 비 일치성을 확인합니다.
assert.isTrue(value) – value가 true인지 확인합니다.
(value === true)
assert.isFalse(value) – value가 false인지 확인합니다.
(value === false)
이외의 다양한 assertion은 docs에서 확인할 수 있습니다.
명세서 초안 작성.(기본적엔 테스트도 작성)
초안을 보고 코드 작성
Mocha(테스트 F/W)를 이용하여 명세서 실행. (에러가 발생하지 않을 때 까지 코드 수정)
모든 테스트를 통과하는 코드 "초안" 완성.
명세서에 지금까지 고려하지 않았던 유즈케이스 추가. (에러가 발생하지 않을 때 까지 코드 수정)
반복