BDD (Behaviour-Driven Development), BDD는 TDD를 기반으로 두고 있다
흔히 알려진 것처럼 TDD는 테스트를 먼저 작성하고 그 테스트를 통과시키는 코드를 작성하는 흐름을 기본으로 한다. 게다가 테스트 단위도 함수 단위로 매우 작아서 작성하는 거의 모든 함수가 테스트 대상에 포함된다. 이상적으로 보일 수 있지만 그만큼 현업에서 사용하기에는 괴리감이 있다.
프로젝트 초기에 야심 차게 TDD를 도입하여 거의 모든 함수에 대한 테스트 케이스를 준비했더라도 개발 중후반에 수정되는 내용에 대해서 깨지는 테스트 케이스를 계속 유지하면서 가져가기란 쉽지 않다. 게다가 로우 레벨의 함수를 나누고 합치고 시그니쳐를 변경하는 리팩토링이라도 하는 날에는 관련 테스트는 모두 깨지며 이를 일일이 맞춰간다는 건 쉽지 않다. 이 말이 어떤 의미인지 실제 TDD를 현업에서 사용해본 사람은 욕지기와 함께 감이 올 것이다.
BDD는 말 그대로 행동 주도 개발이다. 사용자의 행위까지 생각하고 테스트하며 개발한다. BDD는 TDD의 한 종류로, 프론트엔드에서 조금 더 장점이 두드러지는 경향이 있다. 메소드 위주의 TDD보다 행동을 조금 더 강조하기 때문이다.
BDD는 시나리오를 기반으로 테스트 케이스를 작성하며 함수 단위 테스트를 권장하지 않는다. 이 시나리오는 개발자가 아닌 사람이 봐도 이해할 수 있을 정도의 레벨을 권장한다. 하나의 시나리오는 Given, When, Then 구조를 가지는 것을 기본 패턴으로 권장하며 각 절의 의미는 다음과 같다.
Scenario : 테스트 목적에 대한 상황을 설명한다.
Given : 시나리오 진행에 필요한 값을 설정한다.
When : 시나리오를 진행하는데 필요한 조건을 명시한다.
Then : 시나리오를 완료했을 때 보장해야 하는 결과를 명시한다.
위의 내용을 개발 측면에서 더 간략하게 정리하면 테스트 대상의 상태 변화를 테스트하는 것이다.
테스트 대상은 A 상태에서 출발하며(Given) 어떤 상태 변화를 가했을 때(When) 기대하는 상태로 완료되어야 한다. (Then)
또는 Side Effect가 전혀 없는 테스트 대상이라면 테스트 대상의 환경을 A 상태에 두고(Given) 어떤 행동을 요구했을 때(When) 기대하는 결과를 돌려받아야 한다. (Then)
TDD를 하면서 개발을 하다보면 Testcase에 대해서도 계속 유지보수해야하는데 귀찮기도 하고, 마감기한이 정해진 프로젝트라면 일정에 대해 압박을 받을 수도 있다. 그렇기 때문에 매번 개발을 진행하면서 기능에 대해 예외사항에 대해 매번 생각하고 Testcase를 작성하는 것은 생각보다 비용이 많이 들어가는 일이라고 볼 수 있다.
하지만 만약 여기에서 이미 작성된 요구사항이나 기획서가 있고, 그에 맞추어 테스트 케이스를 작성하게 된다면, 위와 같은 시간에 대한 비용이 줄게된다. 바로 이게 BDD이다.
즉, BDD는 TDD에서 파생된 개발 방법론으로, 개발자와 비개발자의 협업 과정을 녹여낸 방법이다.
테스트 대상이 가지고 있는 인터페이스에 대한 테스트 시나리오가 중요한 것이지 내부적으로 사용되는 모든 함수가 명시적인 테스트 대상은 아니다. 인터페이스가 변하지 않는 이상 내부적인 리펙토링을 거친 코드는 테스트 코드 수정없이 모두 통과되어야 한다.
이렇게 보면 BDD든, TDD든 하나만 선택해야하는 거 아니야? 라고 생각이 들 수 있지만(바로 나), 두개는 상호 배타적인 관계가 아니라 상호 보완적인 관계이다. 프로젝트에서 BDD의 테스트케이스로 시나리오 검증을 하고, 해당 시나리오에서 사용하는 각 모듈들은 TDD의 테스트케이스로 검증을 하는 방법이 좋다. 아래 그림을 보면 더 이해하기 쉽다.