Dev/Books

[CleanCode] 9장. 단위 테스트

kyeoneee 2020. 5. 18. 00:51
반응형

목차

  1. TDD 법칙 세 가지
  2. 깨끗한 테스트 코드 유지하기
  3. 깨끗한 테스트 코드
  4. 테스트 당 assert 하나
  5. F.I.R.S.T

TDD 법칙 세 가지

  1. 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다.
  2. 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다.
  3. 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다.

깨끗한 테스트 코드 유지하기

깨끗하지 않은 테스트 코드는 유지 보수에 많은 비용이 필요하게 되고, 테스트 코드가 없으면 프로덕션 코드의 결함율이 높아지게 된다.
테스트 코드는 유연성, 유지보수성, 재사용성을 제공해야 한다.


깨끗한 테스트 코드

깨끗한 테스트 코드는 명료성, 단순성, 풍부한 표현을 바탕으로 한 가독성이 필수이다.


테스트 당 assert 하나

assert 하나만을 사용하기 위해 아래와 같은 방법을 사용 할 수 있다.

  • 테스트를 쪼개서 assert를 분리
  • Template Method 패턴을 사용해 중복을 제거
  • @Before 함수에 given/when 부분을 분리

테스트 함수 하나는 개념 하나만 테스트 해야 한다!


F.I.R.S.T

  • Fast
  • Independent
  • Repeatable
    네트워크가 없는 환경에서도 실행 가능해야 함
  • Self-Validating
    테스트는 성공 혹은 실패로만 결과가 나와야 한다. 별도의 log 등을 통한 확인 작업은 절대 금물
  • Timely
    테스트 코드 작성 -> 실제 코드 작성


참고

BUILD-OPERATE-CHECK 패턴

Given-When-Then 패턴과도 비슷

  • Build (Given)
    Input 데이터를 생성
  • Operate (When)
    Build 단계에서 생성한 데이터로 실제 코드 실행
  • Check (Then)
    Operate 단계의 결과값을 확인

e.g.

public class BowlingTest {
  @Test
  public void FrameTest() {
    // Build (Given)
    Boll testBoll = Boll.getInstance(10);
    Frame frame = Frame.getInstance(Boll);
    // Operate (When)
       Boolean isStrike = frame.isStrike();
    // Check (Then)
    assertThat(isStrike).isTrue();
  }
}

TEMPLATE METHOD 패턴

어떠한 기능의 일부분을 서브 클래스로 캡슐화해 전체 일을 수행하는 구조는 바꾸지 않으면서 특정 단계의 수행 내역을 바꾸는 패턴
e.g.

Original :

public class SumoDeadLift {
  final void start() {
    stand();
    getBarbell();
    doOneRep();
  }

  private void stand() {  // 각 DeadLift 별로 수행 내역이 다른 부분
      System.out.println("다리를 넓게 벌리고 선다.");
  }

  private void getBarbell() {  // 모든 DeadLift의 공통된 알고리즘
    System.out.println("바벨을 들어올린다.");
  }

  private void doOneRep() {
    System.out.println("바벨을 다시 바닥으로 내려놓는다.");
  }
}

public class RumanianDeadLift {
  final void start() {
    stand();
    getBarbell();
    doOneRep();
  }

  private void stand() {
      System.out.println("다리를 골반 넓이 만큼 벌리고 선다.");
  }

  private void getBarbell() {
    System.out.println("바벨을 들어올린다.");
  }

  private void doOneRep() {
    System.out.println("정강이 중간까지만 내려간다");
  }
}

With Template Method Pattern: 모든 DeadLift의 수행 내역이 같은 부분은 추상 클래스에 정의한다.

public abstract class DeadLift {
  final void start() {
    stand();
    getBarbell();
    doOneRep();
  }

  abstract void stand();

  private void getBarbell() {  // 모든 DeadLift의 공통된 알고리즘
    System.out.println("바벨을 들어올린다.");
  }

  abstract void doOneRep();
}

public class SumoDeadLift extends DeadLift {
  @Override
  private void stand() {  // 각 DeadLift 별로 수행 내역이 다른 부분
      System.out.println("다리를 넓게 벌리고 선다.");
  }

  @Override
  private void doOneRep() {
    System.out.println("바벨을 다시 바닥으로 내려놓는다.");
  }
}

public class RumanianDeadLift extends DeadLift {
  @Override  
  private void stand() {
      System.out.println("다리를 골반 넓이 만큼 벌리고 선다.");
  }

  @Override
  private void doOneRep() {
    System.out.println("정강이 중간까지만 내려간다");
  }
}
반응형

'Dev > Books' 카테고리의 다른 글

[DDD Start!] 1장. 도메인 모델 시작  (0) 2020.06.06
[CleanCode] 10장. 클래스  (0) 2020.05.31
[CleanCode] 8장. 경계  (0) 2020.05.18
[CleanCode] 7장. 예외 처리  (0) 2020.05.16
[CleanCode] 6장. 객체와 자료 구조  (0) 2020.05.15