Spring관련 기술/테스트코드

Test Driven Development

솜사탕코튼 2023. 12. 11. 22:44

TDD

  • 프로덕션 코드보다 테스트 코드를 먼저 작성하여 테스트가 구현 과정을 주도하도록 하는 방법론

이게 무슨 이야기일까... (대충 경험상 테스트 코드를 먼저 짠다는게 이해가 안 간다)

 

RED, GREEN, REFACTOR

 

RED

  • 실패하는 테스트 작성
  • 프로덕션 코드(구현부) 없이 테스트를 작성하기 때문에 당연히 실패하기 마련..
  • 먼저 실행해서 빨간불을 봐라

GREEN

  • 초록불을 보기 위해서라면 구현이 엉터리여도 된다.(!??)
  • 테스트 통과, 최소한의 코딩

REFACTOR

  • 구현 코드 개선
  • 테스트 통과 유지

 

코드 구현

https://github.com/beginner0107/cafekiosk

 

GitHub - beginner0107/cafekiosk: 테스트코드 연습 일지

테스트코드 연습 일지. Contribute to beginner0107/cafekiosk development by creating an account on GitHub.

github.com

  public int calculateTotalPrice() {
    int totalPrice = 0;
    for (Beverage beverage : beverages) {
      totalPrice += beverage.getPrice();
    }
    return totalPrice;
  }
  • CafeKiosk.java의 calculateTotalPrice 메서드를 지우고
  • 이 기능을 테스트코드로 먼저 작성하는 과정을 겪을 것이다.
  • 기능: 음료의 가격을 더해서 총 가격을 계산해서 리턴하는 메서드

RED

  public int calculateTotalPrice() {
    return 0;
  }
  @Test
  void calculateTotalPrice() {
    CafeKiosk cafeKiosk = new CafeKiosk();
    Americano americano = new Americano();
    Latte latte = new Latte();

    cafeKiosk.add(americano);
    cafeKiosk.add(latte);

    int totalPrice = cafeKiosk.calculateTotalPrice();

    assertThat(totalPrice).isEqualTo(8500);
  }

 

 

GREEN (빠른 시간 안에 초록불을 본다.!)

  public int calculateTotalPrice() {
    return 8500;
  }

 

 

REFACTOR

  public int calculateTotalPrice() {
    int totalPrice = 0;
    for (Beverage beverage : beverages) {
      totalPrice += beverage.getPrice();
    }
    return totalPrice;
  }

  • 같은 기능이라는 것을 테스트가 보장해주고 있음
  public int calculateTotalPrice() {
    return beverages.stream()
        .mapToInt(Beverage::getPrice)
        .sum();
  }
  • 과감한 리팩토링을 해도 -> 테스트 코드가 보장을 해준다.

 

 

TDD를 쓰는 이유?

  • 선 기능 구현, 후 테스트 작성의 경우
    • 테스트 자체의 누락 가능성
    • 특정 테스트 케이스만 검증할 가능성(해피 케이스)
    • 잘못된 구현을 다소 늦게 발견할 가능성

 

  • 관점의 변화
    • 테스트는 구현부 검증을 위한 보조 수단 VS 테스트와 상호 작용하며 발전하는 구현부
  • 클라이언트 관점에서 피드백을 주는 Test Driven