Published on

Software Testing 9 | 단위 테스트로는 부족해

Authors
  • avatar
    Name
    이건창
    Twitter

Introduction

대규모 테스트 작성

시스템 모든 영역을 단위 테스트로 수행하게 되면 버그를 충분히 찾지 못하거나 작성하기 힘들어. 작성한다고 해도 깨지기 쉬운 테스트 케이스르 만들게 됮.

책에서는 시스템을 테스트 하기 위해 세 가지 케이스로 나눠 테스트하는 방법을 설명해.

  1. 구성 요소와 함께 수행하는 경우
  2. 외부 인프라와 통신하는 경우
  3. 전체 시스템에 대한 종단간 테스트

구성 요소와 함께 수행하는 경우

구성 요소가 많을 때는 이때까지 수행한 명세 기반 테스트와 구조 기반 테스트로 훌륭하게 이겨낼 수 있어. 각각의 구성 요소는 이미 요구 사항이 검증됐기 때문에 더이상 테스트를 작성하지 않아도 돼.

그럼에도 걱정된다면 대규모 시스템 테스트를 수행하는 게 좋아. 하나의 기능을 이루는 거대한 구성 요소를 테스트하는 방법이지.

	/**
	 * 사용자는 5천원을 입금하고 5천원을 출금하면 잔액이 0원 남는다.
	 *
	 * @Given : 사용자는 5천원을 입금하고
	 * @When : 5천원을 출금하면
	 * @Then : 잔액이 0원 남는다.
	 */
	@Test
	void deposit_and_withdraw_5000() throws Exception {
		// given
		var 입금할_돈 = 오천원;
		var 출금할_돈 = 오천원;
		var 나의계좌 = 계좌_정보_조회(MEMBER);

		var 계좌_입금 = 계좌_입금_요청(나의계좌, 입금할_돈, 이메일, 비밀번호);
		계좌_입금.andExpect(status().isOk());

		계좌_조회_요청(나의계좌, 이메일, 비밀번호).andExpect(
			jsonPath(AMOUNT).value(입금할_돈));

		// when
		var 계좌_출금 = 계좌_출금_요청(나의계좌, 출금할_돈, 이메일, 비밀번호);
		계좌_출금.andExpect(status().isOk());

		// then
		계좌_조회_요청(나의계좌, 이메일, 비밀번호).andExpect(
			jsonPath(AMOUNT).value(입금할_돈 - 출금할_돈));
	}

이 방법은 시스템의 경계를 넘지 않기 때문에 통합 테스트가 아니야.

외부 인프라와 통신하는 경우

특히나 데이터 접근 객체가 포함된 경우 테스트 작성이 어려울 수 있어. 먼저 SQL 쿼리에서 테스트 해야 하는 일은 다음과 같아.

  • 명세 기반 테스트
  • 경계 분석
  • 구조적 테스트

우리가 이때까지 학습했던 방법으로 쿼리를 검증하면 돼. 아마 쿼리에서 제일 중요하게 생각할 수 있는 건 범주와 구획 처리하는 방법일 거야. 이런 경우 테스트 구획을 정의할 수 있는 서술적 명세로 확인 가능해.

  • 행을 검색하는 경우
  • 행을 병합하는 경우
  • 행을 그룹화하는 경우
  • 행을 서브쿼리로 검색하는 경우
  • 값이 집계합수에 참여하는 경우
  • 표현식이 존재하는 경우

그 밖에도 출력값 데이터베이스에 대한 제약 사항 등을 검사 해야해.

SQL 테스트를 위한 인프라 설정

쿼리를 테스트하기 위해서는 다음과 같은 준비가 필요해.

  • 데이터베이스 연결 열기
  • 트랜잭션을 열면 커밋하기
  • 데이터베이스 상태 재설정하기

시스템 환경과 유사하게 테스트 하는게 중요해. 작업했다면 롤백하지 말고 커밋한 후 검증하고 테스트가 종료되면 원상태로 돌려야 해.

베스트는 데이터베이스 생성기를 사용하고 단언 API를 재활용하며 필요한 데이터를 최소화 해야해.

다음처럼 인메모리를 활용 할 때 데이터베이스를 초기화 한 후 최소한의 필요한 데이터를 추가 할 수 있어.

@Autowired
private DatabaseCleanup databaseCleanup;
@Autowired
private DataLoader dataLoader;

@BeforeEach
public void setUp() {
  databaseCleanup.execute();
  loadData = dataLoader.loadData();
}

시스템 테스트는 UI까지 테스트하고 있어서 API만 유지보수하는 상황에서 비용이 큰 학습 내용처럼 보여서 생략할게.

마지막으로

개발자는 전체 구성 요소를 함께 테스트하는 것부터 외부 라이브러리나 전체 시스템과의 통합에 이르기까지 대규모 테스트를 작성함으로써 안정적인 개발 환경을 구성 할 수 있어. 추가적으로 이해관계자와 원활한 소통을 위해 큐컴버(cucumber)를 도입하거나 tms(intellij tms)를 도입 할 수 있어.

대규모 테스트를 구성 할 때는 최대한 실제 환경과 유사하게 구성해야 해.