10장. 데이터베이스 테스트

10장. 데이터베이스 테스트

통합 테스트라는 퍼즐의 마지막 조각은 프로세스 외부 관리 의존성이다. 가장 일반적인 예는 애플리케이션 데이터베이스다

실제 데이터베이스를 테스트하면 회귀 방지가 아주 뛰어나지만 설정하기 쉽지 않다

데이터베이스 테스트를 위한 전제 조건

  • 형상 관리 시스템에 데이터베이스 유지
  • 개발자마다 별도의 데이터베이스 인스턴스 사용
  • 데이터베이스 배포에 마이그레이션 기반 방식 적용

데이터베이스를 형상 관리 시스템에 유지

데이터베이스 스키마를 일반 코드로 취급하는것

모델 데이터베이스를 사용하는 것은 데이터베이스 스키마를 유지하는 데 상당히 좋지 못한 방법이다

  • 변경 내역 부재
  • 복수의 원천 정보

참조 데이터도 데이터베이스 스키마다

참조 데이터는 애플리케이션이 제대로 작동하도록 미리 채워야 하는 데이터다.

참조 데이터와 일반데이터를 구별할 수 있는 간단한 방법이 있다 애플리케이션이 데이터를 수정할 수 있으면 일반데이터고 그렇지 않으면 참조 데이터다.

모든 개발자를 위한 별도의 데이터베이스 인스턴스

공유 데이터베이스를 사용하면 개발 프로세스를 방해 하게 된다

  • 서로 다른 개발자가 실행한 테스트는 서로 간섭되기 때문이다
  • 하위 호환성이 없는 변경으로 다른 개발자의 작업을 막을 수 있다

테스트 실행 속도를 극대화 하려면 개발자마다 별도로 데이터베이스 인스턴스를 사용하라

상태 기반 데이터베이스 배포와 마이그레이션 기반 데이터베이스 배포

데이터베이스 배포 방식

  • 상태기반
    • 상태를 형상 관리에 저장함으로써 상태를 명시하고 비교도구가 마이그레이션을 암묵적으로 제어할 수 있게 한다
  • 마이그레이션 기반
    • 마이그레이션을 명시적으로 하지만 상태를 암묵적으로 둔다 데이터베이스 상태를 직접 볼 수 없으며 마이그레이션으로 조합해야 한다

결과적으로 상태 기반 방식은 대다수의 프로젝트에서 실용적이지 않다

데이터베이스 트랜잭션 관리

제품 코드에서 데이터베이스 트랜잭션 관리하기

통합 테스트에서 데이터베이스 트랜잭션 관리하기

테스트에서 트랜젝션이나 작업 단위를 재사용하지 말라

테스트 데이터 생명 주기

  • 통합 테스트를 순차적으로 실행하라
  • 테스트 실행 간에 남은 데이터를 제거하라

병렬 테스트 실행과 순차적 테스트 실행

컨테이너를 사용해 테스트를 병렬로 실행시킬수 있다

단점은

  • 도커 이미지를 유지 보수해야함
  • 각 테스트마다 컨테이너 인스턴스가 있는지 확인해야 함
  • 통합 테스트를 일괄 처리하고
  • 다 사용한 컨테이너는 폐기해야 한다

통합 테스트의 실행 시간을 최소화 해야 하는 경우가 아니라면 컨테이너를 사용하지 않는 것이 좋다

데이터베이스는 개발자당 하나의 인스턴스만 갖는 것이 더 실용적이다

테스트 실행 간 데이터 정리

  • 각 테스트 전에 데이터베이스 백업 복원하기
  • 테스트 종료 시점에 데이터 정리하기
  • 데이터베이스 트랜잭션에 각 테스트를 래핑하고 커밋하지 않기
  • 테스트 시작 시점에 데이터 정리하기

인메모리 데이터베이스 피하기

인메모리 데이터베이스의 장점

  • 테스트 데이터를 제거할 필요가 없음
  • 작업 속도 향상
  • 테스트가 실행될 때마다 인스턴스화 가능

하지만 기능적 일관성이 없기 때문에 사용하지 않는것이 좋다

테스트 구절에서 코드 재사용하기

통합 테스트가 너무 빨리 커지면 유지 보수 지표가 나빠질 수 있다

준비 구절에서 코드 재사용하기

오브젝트 마더(Object Mother) 패턴

테스트 데이터 빌더(Test Data Builder) 패턴

실행 구절에서 코드 재사용하기

대리자(Delegate) 패턴을 활용해서 실행구절을 줄일수 있따

검증 구절에서 코드 재사용하기

플루언트 인터페이스를 사용하면 검증문이 읽기 쉬워진다

테스트가 데이터베이스 트랜잭션을 너무 많이 생성하는가?

빠른 피드백과 유지 보수성의 절충

데이터베이스 테스트에 대한 일반적인 질문

읽기 테스트를 해야 하는가?

읽기를 테스트하기로 결정한 경우에는 실제 데이터베이스에서 통합 테스트하라

리포지터리 테스트를 해야 하는가?

리포지터리는 직접 테스트하지 말고 포괄적인 통합 테스트 스위트의 일부로 취급

참조