포스트

제목 : Testing, Oh my! - jwChung 블로그

링크 : http://jwchung.github.io/testing-oh-my

내용 요약

  • 테스트하기 쉬운 코드어려운 코드를 구분해야한다.

    • 테스트하기 어려운 코드

      • 이메일 발송기능과 같이 테스트 비용이 높아 어려운 경우

      • 불활식성을 지닌 코드

        • 같은 입력 값에 따라 결과가 달라지는 코드

          예) 현재 시간에 따라 오후인지 오전인지 리턴하는 코드

        • 외부세상에서 제공하는 값에 의존하는 코드

          전역 변수, 로컬의 파일, 데이터베이스 레코드 등 값이 다른 존재에 의해 바뀔 수 있다.

      • 부수 효과(Side Effects)

        • 외부세상에 변경을 가하지만 리턴 값을 가지지 못하는 코드

          메일 발송, 파일에 내용 쓰기, 데이터베이스에 데이터 삽입

      • 리턴 타입이 없는 메서드(void)

        • 반환타입이 없는 경우 외부세상을 변경시키는 것이므로 테스트 하기 어려운 코드에 해당.
    • 테스트하기 쉬운 코드

      • 순수함수(pure functions)
        • 테스트하기 어려운 코드의 특징인 불확실성과 부수 효과를 가지지 않는, 외부세상에 단절된 상태를 말함.
      • 리턴타입이 있는 메서드
        • 외부세상과 단절된 상태에서 결과를 반환
        • 리턴 타입은 있지만 외부세상에서 값을 읽어 반환하는 경우라면 테스트하기 어렵다.
  • 테스트하기 어려운 코드에서 테스트하기 쉬운 테스트를 최대한 분리해낸다.

    • public void save(String email, String password){
          if(!email.contains("@"))
              throw new Exception();
          ...
          if(password.length() < 8)
              throw new Exception();
              
          userRepository.save(user);
      }
      

      다음과 같은 코드는 외부세상에 관여를 하는 코드이므로 테스트하기 어려운 코드에 해당한다. 이 곳에서 테스트하기 쉬운 코드를 분리해낸다. 또한 테스트하기 어려운 코드의 경우 메소드 호출 순서의 가장 마지막이 될 수 있도록 놓는다.

      public boolean emailCheck(String email){
          ...
          return true;
      }
          
      public boolean passCheck(String password){
          ...
          return true;
      }
      public void save(String email,String password){
          if(emailCheck(email)&&passCheck(password)){
              ...
              userRepository.save(user);
          }
      }
      
  • IO 작업과 관련된 비순수함수 테스트는 항상 고비용이 요구되는 것이 아니다.

    • 테스트 비용을 줄일 수 있는 도구들이 존재.
  • Function Root

    • 특정 기능 수행의 진입점 역할을 하는 메서드
    • 대체로 외부세상과 소통하는 IO작업을 담고 있어 테스트하기 힘든 코드로 분류
    • 순수함수코드와 비순수함수코드 저네를 가로지는 통합테스트로 검증할 수 있는데, 자동화테스트 비용이 높으면 이를 포기하고 수동테스트로 검증할 수도 있다.
    • Structure Inspection
      • function root내 IO작업을 Test Double로 격리시켜 단위테스트로도 검증할수 있도록 만드는 것.


리뷰

TDD 연습을 시작하면서 조금씩 느끼기 시작하는 건 도대체 어떻게 테스트를 짜야하고 뭘 테스트해야하나 라는 생각이 들었다. 지금 이 포스트를 통해 이런 고민이 전부 해결됬다고는 하지 못하지만 글을 읽어가면서 부분 부분씩 나에게 좋은 영감을 주었다고 생각한다.

글의 주된 흐름은 작성한 코드에서 테스트하기 용이하도록 다시 분리를 한다는 것이 내용이라고 나는 생각한다.

지금 내가 연습하는 것에 이 느낀 점을 살짝 적용해볼 수 있는 것이 있다면

  • 테스트 코드를 작성할 때 좀 더 작은 단위부터 해야한다.
    • 지금 나의 경우에는 볼링 게임을 만들고 있는데, 테스트하려는 범위가 매우 넓다는 것을 느꼈다.
  • 리팩토링 시 순수 함수를 잘 분리할 것.