[Spring] TDD VS BDD

2021. 8. 12. 17:02Spring

TDD 란?

Test Driven Development

2021-08-12-11-47-15.png

  • TDD는 Test Driven Development으로 테스트가 개발을 주도한다는 개념으로 사용된다.
  • TDD는 테스트를 먼저 만들고 테스트를 통과하기 위한 행동들이 모두 개발을 주도하는 것을 목표로 한다.

TDD 예제

Step 1. 우선 만들고 싶은 Class와 해당 TestClass를 생성한다.

public class Example {

}
class HelloBotTest {
     ExampleTest helloBot = new ExampleTest();
}

Step 2. 내가 원하는 기능을 만들고 반환값이 있는지 없는지 만들고 TestClass를 작성한다.

public class Example {

}
class HelloBotTest {
  Example helloBot = new Example();
    @Test
    void showHello() {
        String name = "장장이님";
        String kHello = helloBot.textBot(name);
    }
}
  • 현재 Example 클래스에는 textBot이라는 메서드가 존재하지 않기 때문에 실패한다.

Step 3. Class에 해당 메서드를 통과할 수 있는 간단한 클래스를 구현한다.

public class Example {
    public String textBot(String string) {
        return "hello";
    }
}
class HelloBotTest {
    Example helloBot = new Example();
    @Test
    void showHello() {
        String name = "장장이님";
        String kHello = helloBot.textBot(name);
    }
}
  • Example의 textBot 메서드에서는 어떤 값이 반환되고 좋다. 그냥 일단 컴파일을 성공시키는 것이 목적이다.

Step 4. 해당 Class에서 어떤 결과를 내야할 지 TestClass에서 다시 정의한다.

public class Example {
    public String textBot(String string) {
        return "hello";
    }
}
class HelloBotTest {
    Example helloBot = new Example();
    @Test
    void showHello() {
        String name = "장장이님";
        String kHello = helloBot.textBot(name);

        assertEquals(kHello, "안녕하세요" + name + "반갑습니다.");
    }
}
  • assertEquals 는 JUnit 5에 존재하는 검증문으로 매개변수 2개가 서로 동일하면 테스트 성공을 의미한다. 현재는 return에서는 "hello"를 내뱉기때문에 테스트는 실패한다.

Step 5. 해당 Class에서 해당 TestClass를 통과할 수 있는 로직을 구현한다.

public class Example {
    public String textBot(String string) {
        return "안녕하세요" + string + "반갑습니다.";
    }
}
class HelloBotTest {
    Example helloBot = new Example();
    @Test
    void showHello() {
        String name = "장장이님";
        String kHello = helloBot.textBot(name);

        assertEquals(kHello, "안녕하세요" + name + "반갑습니다.");
    }
}

BDD 란?

행동에 기반하여 TDD를 수행하자는 공통의 이해이다.

BDD에서는 행동에 대한 스펙은 다음과 같다.

  1. Narrative
  2. Given / When / Then

모든 테스트 문장은 Narrative 하게 되어야 한다. 즉, 코드보다 인간의 언어와 유사하게 구성되어야한다.

  • TDD 에서는 사실상 테스트 코드를 이용한 구현에 초점이 맞춰져 있다. 하지만 BDD는 그렇지 않음.!!!!
  • BDD는 TDD를 수행하려는 어떠한 행동과 기능을 개발자가 더 이해하기 쉽게 하는 것이 목적이다.

모든 테스트 문장은 Given / When / Then 으로 나눠서 작성할 수 있어야한다.

  • 위에서 말 한 Narrative를 수행하기 위한 실질적인 개념이라고 생각하면 될 것 같다.

Given

  • 테스트를 위해 주어진 상태
  • 테스트 대상에게 주어진 조건
  • 테스트가 동작하기 위해 주어진 환경

When

  • 테스트 대상에게 가해진 어떠한 상태
  • 테스트 대상에게 주어진 어떠한 조건
  • 테스트 대상의 상태를 변경시키기 위한 환경

Then

  • 앞선 과정의 결과

BDD 예제

  • 앞선 TDD 상황에서 TDD의 흐름을 빼고 BDD의 핵심 개념인 행동에 따른 Given, When, Then 을 도입하면 다음과 같다.

    @Test
    @DisplayName("기존차량삭제")
    void 기존차량삭제테스트() {
        //given
        Car car = new Car(1L, LocalDateTime.now(), LocalDateTime.now(), "0B0240", "0B0240", "11거111", null, null, LocalDate.now(), LocalDate.now(), null, null, (short) 2012, 1L, 4L, false, false, null);
        CarAchakeySpec carAchakeySpec = new CarAchakeySpec(2, 3, false, car);
    
        car.setIsDeleted(false);
        given(carRepository.findById(car.getId())).willReturn(Optional.of(car));
        given(carAchakeySpecRepository.findByCarId(car.getId())).willReturn(carAchakeySpec);
    
        //when
        fmsCarService.deleteCar(car.getId());
    
        //then
        assertThat(car.getIsDeleted()).isEqualTo(true);
        assertThat(car.getId()).isEqualTo(1L);
    }

TDD VS BDD

  • 앞서 말 했지만 TDD와 BDD를 비교한다는 것은 약간 다른 주제츼 이야기라 비교 한다는 것이 힘들것 같지만 개인적으로 비교를 해보자면 다음과 같은 표가 나올 것 같다.

    이름 창시자 Based 핵심 라이브러리
    TDD Kent_beck 시나리오 기반 테스트가 주도하는 개발 JUnit 5, Mockito
    BDD Dan North 행동 기반 자연어와 더 가깝게 TDD JUnit 5, BDDMockito

BDDMockito를 이용한 BDD

  • BDD를 실현하기 위해서는 Given / When / Then 구조를 잘 사용해야한다.
  • 앞선 방법처럼 주석을 이용하여 구분하는 것도 BDD이지만 이보다 더 BDD스럽게 BDD를 실천할 수 있는 방법이 바로 BDDMockito를 사용하는 것이다.

BDDMockito란 Mockito 라이브러리 내에 존재하는 BDDMockito 클래스를 말하며 BDD 지향적인 개발을 mockito에서 API형태로 제공한다.

다음 시간에 Mockito와 BDDMockito에 대해서 조금 더 알아보겠다.

참고사이트