본문 바로가기
✅ 테스트

[의사결정] Testcontainers 사용하기까지

by kukim 2022. 6. 21.

잘못된 내용이나 의견 있다면 편하게 말씀해주세요 🙏🏻

사건의 개요


Spring 프로젝트를 했다. DB와 관련된 통합 테스트 작성하였고 모두 통과하였다.

실제 운영 DB 설정을 위해, 테스트 코드에서 작성한 더미 데이터 스크립트(. sql)를 사용하지 못해 재작성하였다.

 

사건의 원인

테스트 DB 환경 : 인메모리(H2) DB

실제 운영 DB 환경 : MySQL 8.0

 

테스트와 배포 DB 환경이 달랐다. JPA가 제공해주는 Dialet(방언) 기능을 사용하면 두 DB 간 문제가 없었지만, 방언 기능을 사용하지 않는 퓨어 .sql 스크립트에서 문제가 발생했다. (더미 데이터 .sql 스크립트 재사용 못함) 방언 기능을 사용하지 않는 SQL은 없었지만 만약 있었다고 한다면 문제가 발생할 수 있다.(사실 몇 문제가 발생했다. 대소문자 구분 차이, 날짜 쿼리 차이)  

 

책 단위 테스트 10.3.3 인메모리 DB 피하기에선 다음과 같이 말한다.(p353~354)

인메모리 DB는 다음과 같은 장점이 있다.

테스트에서 사용한 데이터를 따로 제거해줄 필요가 없다(테스트 끝나면 삭제), 작업 속도를 향상할 수 있다. 테스트 실행될 때마다 마치 도커처럼 인스턴스화 할 수 있다.

하지만 장점에도 불구하고 사용하지 않는 것이 좋다. 

인메모리 DB는 일반 데이터베이스와 기능적으로 일관성이 없다. 운영-테스트 환경이 일치하지 않는 문제이며, 이 차이로 인해 테스트에서 거짓 양성 또는 거짓 음성이 발생하기 쉽다. 이러한 테스트로 보호 수준을 기대하기 어렵고, 수동으로 회귀 테스트를 수행해야 한다.

인메모리-운영 DB 간 일관성이 100%가 아니다.

 

재발 방지를 위한 조치 항목

 

테스트-운영 DB 환경과 동일성을 위해 테스트 코드 실행 환경을 Docker를 황용해 운영 DB와 동일한 컨테이너 띄워 연결했다. 

하지만 문제가 있었다.

 

관리 비용 

테스트 코드 실행을 위해 로컬에 도커 컨테이너를 띄워야 하는 관리 비용 발생

 

CI/CD 환경

GitHub Actions를 사용해 CI/CD 과정을 자동화하고 있었다. GitHub Actions의 CI 환경에서는 로컬과 다르게 별도의 DB 컨테이너를 띄워주지 않아 테스트 코드가 실패하였다. 이를 위해 Docker 위에 DB 컨테이너를 띄우지 않고 실제 인스턴스(e.g. AWS ec2 또는 RDS)를 연결하여 테스트할 수 있겠지만 비용적인 문제가 있다.

 

이를 위해 Testcontainers를 도입하기로 했다.

Testcontainers는 JUnit 테스트를 지원하는 Java 라이브러리이다. 도커 컨테이너나 웹 브라우저 등 실제 운영 환경과 같은 테스트 환경을 사용할 수 있다.

 

장점

- 인메모리 DB를 사용하지 않고 실제 운영 DB와 동일한 환경에서 테스트할 수 있다.

- CI/CD 환경에서 테스트할 때 별도의 외부 인스턴스를 띄우지 않고 도커 컨테이너를 손쉽게 띄우고 내릴 수 있다.

- 별도의 도커 컨테이너 관리를 하지 않아도 테스트마다 독립적으로 사용할 수 있다

- 특정 DB 뿐만 아니라 Nginx, Elasticsearch, 커스텀한 도커 이미지에도 적용할 수 있다.

 

단점

- 테스트 코드 작성 비용이 증가한다.

- 테스트 코드 실행 속도가 느리다. (테스트 실행 시 도커를 띄우고 내린다.)

- 작업 속도 저하된다.

해당 경험에서 얻은 교훈

테스트 - 운영 환경 통일

일치하지 않아 테스트가 깨지는 경우가 발생할 수 있다.

이는 거짓 양성(운영 코드에 문제가 없지만 테스트는 실패)과 거짓 음성(테스트는 통과하지만 운영 코드에 버그가 있는 경우)이 생긴다.

또한 이러한 반복된 증상은 테스트 코드를 신뢰할 수 없게 되고 더 이상 테스트 코드를 작성하지 않게 된다.

 

새로운 기술 도입 장단점

Testcontainers를 학습/적용하며 자동으로 테스트 환경에 맞는 컨테이너를 띄우고 지우는 것에 놀라고 흥분(?)됐다. 

하지만 두 가지 고민이 들었다.

큰 기술 : 현재 프로젝트는 토이 프로젝트이다. Testcontainers 적용은 과하지 않나 생각이 든다. 하지만 CI 환경에서 테스트 통과를 위해 별도의 인스턴스를 띄우거나, 아예 테스트를 하지 않는 것보단 좋아 보인다.

생각보다 오래 걸리는 테스트 실행 시간 : 매번 도커를 띄우고 내리는 데 체감상 1~4초 시간이 증가했다.

 

 

2022.06.23 - [✅ 테스트] - Testcontainers에서 MySQL 사용해보기 (테스트 환경에서 자동으로 MySQL 컨테이너 띄우고 내리기)


⛓ Reference

- BackGroudImage : Elena Mozhvilo

- Testcontainers Docs

- 책 단위 테스트 소개

Testcontainers logo

댓글