테스트 작성 관련 내용 정리

jihunnit·2024년 9월 16일
1

TIL

목록 보기
18/19
post-thumbnail
  1. 한 문단에 한 주제

    • if, for 등 논리 구조가 들어갈 경우 여러 주제가 포함될 확률이 높고, test를 읽는 사람이 자연스럽게 읽기 힘듦
      (생각을 하면서 읽어야 됨)
    • 테스트가 @DisplayName에서 한 문장으로 설명될 수 있는가?
  2. 완벽하게 제어하기

    • 제어할 수 없는 변수(ex, LocalDateTime.now()) 는 상위 클래스에서 주입받는걸로 변경
    • 외부 시스템에 대해 Mocking 처리를 하고 테스트 구성을 하자
  3. 테스트 환경의 독립성 보장

    • 테스트가 깨져도 when, then 절에서 깨져야 하는데, 테스트 구성을 하는 given 절에서 실패하면 논리적으로 맞지 않음
  4. 각 테스트 사이의 독립성 보장

    • 언제 수행되었든 항상 같은 결과 보장
    • 테스트 수행 환경을 항상 동일하게
    • 공유자원 사용 배제
  5. 한 눈에 들어오는 Text Fixture
    Text Fixture -> 테스트를 위해 원하는 상태로 고정시킨 객체

    • setUp 같은 함수 사용하면 모든 Test에 영향을 미침
    • BeforeEach 등 함수는 각 테스트 입장에서 해당 메서드 내부를 모르고, 수정해도 아무 변화가 없다면 사용 가능
  6. Text Fixture 클렌징

    • deleteAll과 deleteAllInBatch의 차이
      -> deleteAll은 전체를 Select해서 건 당 delete로 지워줘서 쿼리가 길어짐
      -> 다만 매핑된 다른 테이블도 다 건 당 delete로 지줌
      -> deleteAll과 deleteAllInBatch의 성능 차이가 발생
    • 지울때도 순서 따라서 잘 지워야 함 -> 외래키 제약 조건 방지
  7. ParamiterizedTest

    • @ParamiterizedTest를 통해 여러 case에 대해 test를 한 번에 수행

예시코드

@DisplayName("상품 타입이 재고 타입인지 체크한다.")
@CsvSource({"HANDMADE,false", "BOTTLE,true", "BAKERY,true"})
@ParameterizedTest
void containsStockType3(ProductType productType, boolean expected){
    //given
    //when
    boolean result = ProductType.containsStockType(productType);
    //then
    assertThat(result).isEqualTo(expected);
}
  1. DynamicTest
    • @TestFactory를 사용하고, 아래에서 여러 행동을 결합하여 특정 시나리오대로 테스트 진행

예시코드

@DisplayName("재고 차감 시나리오")
@TestFactory
Collection<DynamicTest> stockDeductionDynamicTest(){

    //given
    Stock stock = Stock.create("001", 1);

    return List.of(
             DynamicTest.dynamicTest("재고를 주어진 개수만큼 차감할 수 있다.", () -> {
                //given
                int quantity = 1;

                //when
                stock.deductQuantity(quantity);

                //then
                assertThat(stock.getQuantity()).isZero();
            }),
            DynamicTest.dynamicTest("재고보다 많은 수의 수량으로 차감 시도하는 경우 예외가 발생한다.", () -> {
                //given
                int quantity = 1;

                //when //then
                assertThatThrownBy(() -> stock.deductQuantity(quantity))
                        .isInstanceOf(IllegalArgumentException.class)
                        .hasMessage("차감할 재고 수량이 없습니다.");
            })
    );
}
  1. 테스트 환경 통일

    • ActiveProfile 차이 등으로 인해 테스트시 SpringBoot 서버가 새로 뜸. 이는 자원 낭비
    • 환경을 통합하는 부모 클래스를 만들고, 이를 상속하게 하면서 이러한 테스트 시 서버 재가동 줄일 수 있음
    • Mock의 경우에는 또 다른 환경이므로 이에 대핸 구분 필요 (Mock을 사용하는 class끼리만 통합)
    • Presentation 계층의 경우 @SpringBootTest가 아닌 @WebMvcTest 사용하므로 통합 어려움, 같은 계층끼리만 통합
  2. private 메서드의 테스트

    • 할 필요 없음
    • 외부(호출하는 입장)에서는 private method는 알 필요가 없음
    • private method를 사용하는 쪽에서 test를 진행하면 자연럽게 해당 private method의 검증도 되는 구조
    • 계속 이러한 필요가 생각난다면, 오히려 클래스의 책임 분리에 대해 생각할 떄 일지도..
  3. production에서는 필요 없고 test에만 필요한 코드라면?

    • 만들어도 되지만 보수적으로 접근
    • 정말 꼭 필요한 경우에만 작성하자

츨처 - https://www.inflearn.com/course/practical-testing-%EC%8B%A4%EC%9A%A9%EC%A0%81%EC%9D%B8-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B0%80%EC%9D%B4%EB%93%9C/dashboard

profile
인간은 노력하는 한 방황한다

0개의 댓글