BDD를 테스트 문법으로만 이해하면 놓치게 되는 것

먼저 용어부터 짚고 가야 한다. 테스트 주도 개발(TDD)은 구현보다 테스트를 먼저 작성하고 그 테스트를 통과시키는 방향으로 코드를 발전시키는 개발 방식이다. 행동 주도 개발(BDD)은 소프트웨어 개발자이자 컨설턴트인 Dan North가 TDD를 가르치고 적용하는 과정에서 생긴 혼란을 줄이기 위해 제안한 접근이다.
BDD를 처음 배울 때 가장 먼저 접하는 것은 대개 주어진 상황-행동-결과(Given / When / Then) 형식이다. 그래서 BDD를 “테스트를 읽기 좋게 쓰는 형식” 정도로 받아들이기 쉽다. 그런데 Dan North의 Introducing BDD를 다시 읽어보면 출발점이 조금 다르다. 그 글에서 그는 TDD를 가르치고 적용하는 과정에서 개발자들이 반복해서 부딪히는 혼란, 이를테면 무엇부터 테스트해야 하는지, 테스트 이름을 어떻게 지어야 하는지, 실패한 테스트를 어떻게 해석해야 하는지 같은 문제를 언급한다. 그리고 그 혼란을 줄이기 위한 응답으로 BDD를 제시한다.
즉 BDD의 시작점은 새로운 문법 자체가 아니라, 테스트(test)보다 행동(behaviour)이라는 말을 쓰는 편이 개발자와 비즈니스 모두에게 더 분명하다는 문제의식에 가깝다.
Dan North가 바꾸려 했던 것은 테스트 코드의 문체보다 사고방식이다
Introducing BDD에서 Dan North는 테스트 메서드 이름을 문장처럼 쓰고, ~해야 한다는 뜻의 should로 시작하게 하면 현재 클래스가 책임져야 할 행동이 더 잘 드러난다고 설명한다. 이때 중요한 건 문장이 예뻐진다는 사실이 아니다. 어떤 테스트 이름이 점점 길고 어색해진다면, 그건 지금 클래스가 너무 많은 일을 하고 있다는 신호일 수 있다는 점이다.
그가 예로 드는 AgeCalculator 사례도 같은 맥락이다. 검증기 안에 들어 있던 나이 계산 규칙이 점점 복잡해지자, 그 행동을 별도 객체로 분리한다. 이 장면에서 BDD는 단순히 “테스트를 먼저 쓴다”가 아니라, 행동 이름을 붙이는 과정에서 책임 경계를 더 분명하게 만드는 도구로 보인다.
이 대목은 확인 가능한 사실로 정리할 수 있다.
- Dan North는 BDD를 TDD를 더 접근 가능하고 효과적으로 만들기 위한 응답으로 설명한다.
- 그는
should같은 문장형 이름이 행동을 더 분명하게 드러낸다고 말한다. - 그 과정에서 클래스 책임이 지나치게 커졌는지도 더 빨리 드러난다.
여기까지는 추상적 해석이 아니라 원문에서 직접 확인되는 흐름이다.
BDD가 요구사항 쪽으로 확장되는 지점도 문서에서 바로 확인된다
Dan North의 What’s in a Story?는 이 지점을 더 분명하게 보여준다. 글 첫머리에서 그는 BDD를 바깥의 비즈니스 결과에서 안쪽 구현으로 내려오는 아웃사이드-인(outside-in) 방법론이라고 부른다. 그리고 기능 하나를 사용자 이야기인 스토리(story)로 잡고, 그 안에 수용 기준인 인수 기준(acceptance criteria)을 시나리오 형태로 담는 구조를 제시한다.
그 글에서 확인되는 핵심 형식은 익숙하다.
As a [role]
I want [feature]
So that [benefit]
그리고 acceptance criteria는 시나리오로 이어진다.
Given [context]
When [event]
Then [outcome]
여기서 중요한 건 이 형식이 “꼭 이렇게만 써야 한다”는 강제 규칙이 아니라는 점이다. Dan North는 다른 형식을 써도 BDD일 수 있다고 분명히 적는다. 다만 이 템플릿이 여러 프로젝트에서 잘 작동해 왔고, 역할·기능·이익·완료 조건을 한 번에 드러내는 장점이 있다고 설명한다.
이 때문에 BDD를 Given / When / Then을 쓰는 테스트 습관으로만 이해하면 반만 본 셈이 된다. 원문에 가까운 이해는 오히려 이쪽이다. BDD는 요구사항의 범위와 완료 조건을 여러 역할이 함께 같은 언어로 설명하려는 시도다.
주어진 상황 / 행동 / 결과는 BDD의 전부가 아니라 예시를 구조화하는 표현이다
소프트웨어 저술가이자 아키텍처 컨설턴트인 Martin Fowler의 Given When Then 글은 이 점을 잘 정리해 준다. 그는 이 스타일이 BDD와 강하게 연결되어 있지만, 기본 아이디어 자체는 더 넓은 예시 기반 명세(specification by example)나 준비-실행-검증(Arrange / Act / Assert)과도 통한다고 설명한다. 즉 주어진 상황 / 행동 / 결과(Given / When / Then)는 유용한 표현 형식이지만, 그 형식만 쓴다고 자동으로 BDD가 되는 것은 아니다.
BDD 도구로 널리 쓰이는 Cucumber의 Gherkin 문서도 비슷하다. 공식 문서는 Gherkin을 실행 가능한 명세를 읽기 쉽게 쓰기 위한 키워드 언어로 설명한다. 그리고 기능(Feature), 시나리오(Scenario), Given, When, Then 같은 키워드 뒤의 문장은 스텝 정의(step definition), 즉 실제 테스트 코드와 연결되는 정의로 이어진다고 밝힌다.
여기서 정리할 수 있는 사실은 두 가지다.
주어진 상황 / 행동 / 결과는 행동 예시를 읽기 쉽게 구조화하는 형식이다.- Gherkin은 그 예시를 실행 가능한 명세로 연결하는 도메인 특화 언어(DSL)다.
이 둘을 합치면 BDD의 중요한 면 하나가 보인다. 설명용 문서와 자동화 테스트가 완전히 따로 놀지 않게 하려는 시도라는 점이다.
mock을 BDD의 중심이라고 말하면 범위가 너무 좁아진다
기존 원고는 mocking을 BDD의 핵심처럼 다루고 있었는데, 자료를 다시 보면 그렇게까지 말하기는 어렵다. Dan North의 글에서 mock은 행동을 분리하고 협력 객체를 명확히 보기 위한 실용 도구로 등장하지만, BDD 전체를 대표하는 개념은 아니다.
Martin Fowler의 Test Double은 이 구분을 더 분명하게 만들어 준다. 그 글에서 그는 test double을 프로덕션 객체를 대신하는 모든 대체 객체의 총칭으로 두고, 그 아래에 dummy, fake, stub, spy, mock을 나눈다. 즉 mock은 여러 대체 수단 중 하나다.
그래서 자료 기준으로 더 정확한 표현은 다음과 같다.
- BDD는 mock 프레임워크 사용법이 아니다.
- mock은 행동을 검증할 때 쓸 수 있는 여러 테스트 대역(test double) 중 하나다.
- BDD의 더 큰 관심사는 시스템이 어떤 상황에서 어떤 결과를 보여야 하는지를 분명하게 말하는 데 있다.
지금 기준으로 BDD를 다시 한 줄로 정리하면
Dan North, Martin Fowler, Cucumber 문서를 함께 놓고 보면 BDD는 테스트 문법 하나를 가리키는 말이 아니다. 더 가깝게 말하면, 요구사항과 테스트와 코드가 서로 다른 말을 쓰지 않도록 행동 중심 언어를 맞추려는 접근이다.
그래서 BDD를 이해할 때 먼저 물어야 할 질문도 바뀐다.
- 이 테스트가 예쁜가?
- 이 시나리오가 자동화되는가?
보다 앞서,
- 이 기능의 행동을 팀이 같은 말로 설명할 수 있는가?
- 완료 조건이 시나리오 수준에서 분명한가?
를 묻게 된다. 자료를 그대로 따라가면, BDD의 본질은 문법보다 언어에 더 가깝다.