BDD(Behaviour-Driven Development)

비즈니스 중심의 행위 주도 개발 방법론을 말한다.

테스트 대상의 상태 변화를 테스트하는 것이고 시나리오를 기반으로 테스트하는 패턴을 권장한다.

TDD(Test-Driven Development)는 단위 테스트 코드 자체에 중점을 두지만, BDD는 TDD를 포함하며 시나리오 기반이다 보니 큰 관점에서 비즈니스 요구 사항 중심의 개발 방법론이라고 보는 것이다.

 

💡 TDD(Test-Driven Development)

테스트를 통과하는 코드를 작성하자는 모토로 개발을 진행하는 개발 방법론 중 하나이다.

우선 구현해야할 기능의 테스트를 통과하는 코드를 간단히 작성 후, 나중에 그 코드를 표준에 맞는 좋은 코드로 리팩토링 하는 방법이다.

 


시나리오 기반의 테스트 패턴? - Given When Then

시스템의 동작을 지정하는 테스트를 나타내는 스타일 중 하나이자 BDD의 일부이다. 그 패턴의 내용은 아래와 같다.

  • Given : 테스트 메서드에다가 시나리오 진행에 필요한 조건을 미리 설정해두는 단계이다. 
  • When : 시나리오를 진행 시 필요한 변화를 명시한다.
  • Then : 시나리오를 완료했을 때 예상되는 결과를 명시한다.

아래 Mockito 프레임워크 예제 코드를 보며 어떤 방식인지 확인해보자. 우선 BDDMockito가 적용되기 전이다.

💡 Mockito란 자바 진영의 Mocking 프레임워크 중 하나이며 자세한 내용이 궁금하다면 Mockito - Mockito란, Stubbing, Mock 객체 생성 방법과 동작 원리 포스팅을 참고 바란다.

@Test
void bddMockitoPostingAlwaysTrue() {
    // given
    when(bddMockitoPosting.hasStar()).thenReturn(true);

    // when
    boolean actual = bddMockitoPosting.hasStar();

    // then
    assertThat(actual).isTrue();
}

우선 given 부분에 bddMockitoPosting의 hasStar() 메서드가 호출되면 true를 반환하라는 조건을 미리 설정해둔다.

다음으로 when 부분에 hasStar() 메서드를 실제로 호출한 후,

마지막으로 then 부분에서 isTrue() 메서드로 hasStar() 메서드가 실제로 true를 반환했는지 검증한다.
시나리오로 정리하자면 'bddMockitoPosting.hasStar() 메서드가 true만 반환하는 상태에서 출발하며(Given), hasStar() 메서드를 실행했을 때(When), true를 반환해야 한다(Then)'가 된다.

 

그런데 given 부분을 보면 Mockito.when() 메서드를 사용하고 있다. 네이밍 규칙 관점에서 보면 충분히 혼동을 줄 수 있다. 그래서 이 혼동을 없애고자 등장한 것이 BDDMockito이다.


BDDMockito

BDD를 사용하여 테스트코드 작성시 시나리오에 맞게 테스트 코드가 읽히도록 하는 개선된 Mockito 프레임워크이다.

먼저 아래 예제코드는 BDDMockito를 적용하기 전이다.

@Test
void bddMockitoPostingAlwaysTrue() {
    when(bddMockitoPosting.hasStar()).thenReturn(true);

    assertThat(bddMockitoPosting.hasStar()).isTrue();
}

적용전에는 문맥이 'A가 호출될때 B를 리턴해라. 이제 검증을 해보자' 처럼 되는 것을 볼 수 있다.

 

그다음으로 위 예제코드에 BDDMockito를 적용한 후이다.

@Test
void bddMockitoPostingAlwaysTrue() {
    // given
    given(bddMockitoPosting.hasStar()).thenReturn(true);

    // when
    boolean actual = bddMockitoPosting.hasStar();

    // then
    assertThat(actual).isTrue();
}

적용후에는 문맥이 'A는 호출된다면 B를 리턴할것이고, 이제 A가 호출됐으니, 검증을 해보자'로 변경됐다.
그래서 테스트 대상이 어떤 상태로 출발하는지(given)와 실제로 어떤 상태로 변경됐는지(when)의 분리됐고
문장구조도 시간순서를 고려해 개선했으므로 사람이 순서대로 읽기 좀 더 편해진 것이다.

given 부분에 when() 메서드가 아닌 BDDMockito.given() 메서드가 사용돼 Given When Then의 이름에 맞춰진 것을 확인할 수 있다.

 

이 외에도 then 부분에 Mockito.verify() 메서드가 then().should()로 대체될 수 있다.

@Test
void bddMockitoPostingAlwaysTrue() {
    // given
    given(bddMockitoPosting.hasStar()).thenReturn(true);

    // when
    boolean actual = bddMockitoPosting.hasStar();

    // then
    assertThat(actual).isTrue();
    
    // verify
    // hasStar() 메서드가 1번 호출 됐는지 검증한다.
    then(bddMockitoPosting).should().hasStar();
}

 

출처

BDD(Behaviour-Driven Development)

en.wikipedia.org/wiki/Behavior-driven_development

 

Given When Then

martinfowler.com/bliki/GivenWhenThen.html

github.com/mockito/mockito/wiki/Mockito-features-in-Korean#19-aliases-for-behavior-driven-development-180-이상

 

Mockito와 BDDMockito는 뭐가 다를까?

woowacourse.github.io/javable/post/2020-09-29-compare-mockito-bddmockito/