본문 바로가기
언어/JavaScript

Behavior Driven Development(BDD)

by seacode 2025. 4. 10.

소프트웨어 테스팅 방법론 중 하나

- test, document, example 을 모두 모아놓은 개념

- 명세서(spec) 작성 시, 아래와 같은 양식으로 작성할 수 있다.

describe("pow", function() {

  it("주어진 숫자의 n 제곱", function() {
    assert.equal(pow(2, 3), 8);
  });

});

명세서의 구성 요소

1. describe("제목", function() { ... })

  • 구현하고자 하는 기능에 대한 설명
  • it 블록을 모아주는 역할

2. it("useCase 설명", function() {...})

  • 누구나 읽을 수 있도록 자연어로 작성
  • function은 유즈 케이스 테스트 함수가 들어간다.

3. assert.equal(val1, val2)

  • 제대로 구현했다면 해당 구문이 정상 실행

개발 순서

  1. 명세서 초안을 작성합니다. 초안엔 기본적인 테스트도 들어갑니다.
  2. 명세서 초안을 보고 코드를 작성합니다.
  3. 코드가 작동하는지 확인하기 위해 Mocha라 불리는 테스트 프레임워크를 사용해 명세서를 실행합니다.(Mocha에 대해선 아래에서 다룰 예정입니다.) 이때, 코드가 잘못 작성되었다면 에러가 출력됩니다. 개발자는 테스트를 모두 통과해 에러가 더는 출력되지 않을 때까지 코드를 수정합니다.
  4. 모든 테스트를 통과하는 코드 초안이 완성되었습니다.
  5. 명세서에 지금까진 고려하지 않았던 유스케이스 몇 가지를 추가합니다. 테스트가 실패하기 시작할 겁니다.
  6. 세 번째 단계로 돌아가 테스트를 모두 통과할 때까지 코드를 수정합니다.
  7. 기능이 완성될 때까지 3~6단계를 반복합니다.

명세서 실행하기

- mocha, chai, sinon 등이 있는데, 이 3가지는 브라우저나 서버를 가리지않고 사용 가능하다.

<!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) {
      /* 코드를 여기에 작성합니다. 지금은 빈칸으로 남겨두었습니다. */
    }
  </script>

  <!-- 테스트(describe, it...)가 있는 스크립트를 불러옵니다. -->
  <script>
    describe("pow", function() {

    it("raises to n-th power", function() {
    assert.equal(pow(2, 3), 8);
    });

    });
  </script>

  <!-- 테스트 결과를 id가 "mocha"인 요소에 출력하도록 합니다.-->
  <div id="mocha"></div>

  <!-- 테스트를 실행합니다! -->
  <script>
    mocha.run();
  </script>
</body>

</html>

- mocha를 위와 같이 cdn을 통해 바로 불러올 수 있다.

- 또한 테스트는 아래와 같이 it 블록을 하나씩 분리시켜 작성하는게 얻을 수 있는 정보가 많아진다. (1테스트 = 1가지만 확인 원칙)

describe("pow", function() {

  it("2를 세 번 곱하면 8입니다.", function() {
    assert.equal(pow(2, 3), 8);
  });

  it("3을 네 번 곱하면 81입니다.", function() {
    assert.equal(pow(3, 4), 81);
  });

});

 

중첩 describe

describe("pow", function() {

  describe("x를 세 번 곱합니다.", function() {

    function makeTest(x) {
      let expected = x * x * x;
      it(`${x}을/를 세 번 곱하면 ${expected}입니다.`, function() {
        assert.equal(pow(x, 3), expected);
      });
    }

    for (let x = 1; x <= 5; x++) {
      makeTest(x);
    }

  });

  // describe와 it을 사용해 이 아래에 더 많은 테스트를 추가할 수 있습니다.
});

- makeTest 함수는 for문 안에서만 쓰이므로 이렇게 묶어놨다.

- 중첩된 describe 를 쓰면 그룹을 만들 수 있으며, 하위 그룹을 정의할 때 사용 가능하다.

- 하위 그룹은 결과 출력창에서 들여쓰기 되어 출력된다.

 

before/after 그리고 beforeEach/afterEach

- 보통 초기화 용도로 사용함 (카운터 변수를 0으로 만들거나, 테스트가 바뀔 때 마다 해줘야하는 작업에 사용함)

- before 는 전체 테스트가 실행되기 전에 실행.

- after 는 전체 테스트가 실행된 후에 실행.

- beforeEach 는 매 it이 실행되기 전에 실행.

- afterEach 는 매 it이 실행된 후에 실행.

describe("test", function() {

  before(() => alert("테스트를 시작합니다 - 테스트가 시작되기 전"));
  after(() => alert("테스트를 종료합니다 - 테스트가 종료된 후"));

  beforeEach(() => alert("단일 테스트를 시작합니다 - 각 테스트 시작 전"));
  afterEach(() => alert("단일 테스트를 종료합니다 - 각 테스트 종료 후"));

  it('test 1', () => alert(1));
  it('test 2', () => alert(2));

});
테스트를 시작합니다 - 테스트가 시작되기 전          (before)
단일 테스트를 시작합니다 - 각 테스트 시작 전         (beforeEach)
1
단일 테스트를 종료합니다 - 각 테스트 종료 후         (afterEach)
단일 테스트를 시작합니다 - 각 테스트 시작 전         (beforeEach)
2
단일 테스트를 종료합니다 - 각 테스트 종료 후         (afterEach)
테스트를 종료합니다 - 테스트가 종료된 후            (after)

 

SPEC 확장하기

- 명세서 작성 시, BDD에서는 "실패할 수 밖에 없는" 테스트를 추가시켜서 통과할 때 까지 개선해나가는 작업의 반복을 기본으로 한다.

'언어 > JavaScript' 카테고리의 다른 글

화살표 함수  (0) 2025.04.08
함수 표현식  (0) 2025.04.08
function 사용법  (0) 2025.04.07
반복문  (0) 2025.04.01
?? 연산자  (0) 2025.03.28