ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 테스트가 어려운 영역을 분리하기
    Backend/테스트 코드 2024. 9. 26. 22:18

     

    테스트가 어려운 코드 영역 구분

    주문 메서드 작성

    키오스크 주문은 10시 ~ 22시 사이로 가능하다. 그 시간 외에는 IllegalArgumentException 예외가 발생한다.

    @Getter
    public class CafeKiosk {
    
        public static final LocalTime SHOP_OPEN_TIME = LocalTime.of(10, 0);
        public static final LocalTime SHOP_CLOSE_TIME = LocalTime.of(22, 0);
    
        private final List<Beverage> beverages = new ArrayList<>();
    
        public Order createOrder() {
            LocalDateTime currentDateTime = LocalDateTime.now();
            LocalTime currentTime = currentDateTime.toLocalTime();
            if(currentTime.isBefore(SHOP_OPEN_TIME) || currentTime.isAfter(SHOP_CLOSE_TIME)) {
                throw new IllegalArgumentException("주문 시간이 아닙니다. 관리자에게 문의하세요.");
            }
            return new Order(currentDateTime, beverages);
        }
        
    }

    테스트 코드 작성

    아래 테스트는 통과할 수도, 통과하지 못할 수도 있다. createOrder() 메서드는 현재 시간인 currentDateTime을 사용한다. 테스트를 성공하기 위해서는 10시 ~ 22시 사이어야 하고, 그게 아니라면 테스트에 실패하게 된다.

    class CafeKioskTest {
        @Test
        void createOrder() {
            CafeKiosk cafeKiosk = new CafeKiosk();
            Americano americano = new Americano();
    
            cafeKiosk.add(americano);
    
            Order order = cafeKiosk.createOrder();
            assertThat(order.getBeverages()).hasSize(1);
            assertThat(order.getBeverages().get(0).getName()).isEqualTo("아메리카노");
        }
    }

     

    메서드 내부에서 현재 시간을 입력받고 있기 때문에 테스트에 어려움이 있다. 테스트에 어려움이 있는 영역을 식별하였기 때문에 이를 외부로 분리하자. 외부로 분리한다는 것은 파라미터로 입력받을 수 있도록 한다는 의미다.

    아래는 현재 시간을 파라미터로 입력받을 수 있도록 하였다.

    @Getter
    public class CafeKiosk {
    
        public static final LocalTime SHOP_OPEN_TIME = LocalTime.of(10, 0);
        public static final LocalTime SHOP_CLOSE_TIME = LocalTime.of(22, 0);
    
        private final List<Beverage> beverages = new ArrayList<>();
        
        public Order createOrder(LocalDateTime dateTime) {
        //        LocalDateTime currentDateTime = LocalDateTime.now();
            LocalTime currentTime = dateTime.toLocalTime();
            if(currentTime.isBefore(SHOP_OPEN_TIME) || currentTime.isAfter(SHOP_CLOSE_TIME)) {
                throw new IllegalArgumentException("주문 시간이 아닙니다. 관리자에게 문의하세요.");
            }
            return new Order(dateTime, beverages);
        }
    }

     

    테스트가 어려운 부분을 외부로 분리하면서 항상 성공하는 테스트 코드를 작성할 수 있게 되었다. 또한 현재 시간을 직접 입력받기 때문에 경계값 테스트 또한 가능해졌다.

    • createOrderWithCurrentTime() : 성공 테스트 케이스
    • createOrderOutsideOpenTime() : 실패 테스트 케이스

     

    결론

    테스트하기 어려운 영역이 존재한다면 이를 외부로 분리할 수 없는지 생각해보자. 파라미터를 통해 직접 입력받을 수 있도록 한다면 테스트가 가능한 코드 또한 많아진다.

     

    아래는 테스트를 어렵게 만드는 대표적인 예시이다.

    • 관측할 때마다 다른 값에 의존하는 코드
      • 현재 날짜/시간, 랜덤 값, 사용자 입력 …
    • 외부 세계에 영향을 주는 코드
      • 데이터베이스 기록, 메일 전송, 파일 기록 …
Designed by Tistory.