사내에서 통합 테스트를 진행하기 위해 Test를 위한 DB를 Docker-compose로 말아 사용하기로 했다!
기존에 존재하는 서비스에서 통합 테스트를 구현하는 데 도움이 될 수 있는테스트 전용 DB를 구축하는 방법을 기술해보려고 한다.
기술 스택은 Nestjs, Typescript, MariaDB에서 세팅한 기준이다!
먼저, Docker-compose.yml 파일을 먼저 구성해보자
테스트 코드를 실행할 때 사용할 DB 컨테이너를 생성하기 위한 환경 파일이다.
version: '3.7'
services:
maria:
container_name: wd-mysql-container // 1
image: mariadb:latest // 2
ports:
- "33306:3306" // 3
environment:
MYSQL_USER: ${TEST_DB_USER} // 해당 ${} 내의 변수는 env 파일내 값을 따른다.
MYSQL_PASSWORD: ${TEST_DB_PASSWORD} // process.env를 생각하면 된다.
MYSQL_ROOT_PASSWORD: ${TEST_DB_PASSWORD}
MYSQL_DATABASE: ${TEST_DB_DATABASE}
volumes: // 4
- ./sql/init.sql:/docker-entrypoint-initdb.d/init.sql
자동으로 실행한다./docker-entrypoint-initdb.d/init.sql이다. << 즉, ./sql/init.sql에 있는 파일을 자동으로 실행하는 경로에 공유함으로써 init.sql 파일이 자동으로 실행되는 것이다.상대 경로이다.테스트를 진행하기 위해 테스트용 DB에 권한을 부여, 기본 테이블 생성 및 기본 데이터 생성을 위한 SQL 파일이다.
docker-compose.yml의 volume 부분에 의해 컨테이너가 생성되면 아래의 sql 파일이 최초로 실행된다!
추가 레퍼런스는 해당 블로그를 참고하면 도움이 많이 될 것이다!
-- init.sql
-- 사용자가 존재하는지 확인합니다.
SELECT User FROM mysql.user WHERE User = 'test';
-- 사용자가 존재하는 경우에만 삭제합니다.
DROP USER IF EXISTS 'test'@'%';
CREATE USER 'test'@'%' IDENTIFIED BY 'test';
GRANT ALL PRIVILEGES ON *.* TO 'test'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
-- 권한 설정
-- 테이블 세팅
CREATE TABLE ..
-- 디폴트 데이터 세팅(어드민 유저 또는 일반 유저)
INSERT ...
...
"------------ e2e TEST-----------------------": "",
"test:e2e:pre": "docker-compose up -d", // 통합 테스트 전 테스트 디비 실행
"test:e2e:done": "docker-compose down", // 통합 테스트 마무리 후 컨테이너 삭제
"test:e2e": "npm run test:e2e:pre && npx cross-env NODE_ENV=test jest --config ./test/jest-e2e.json --detectOpenHandles && npm run test:e2e:done" // 통합 테스트 실행
...
npm/yarn run test:e2e를 실행하면 npm run test:e2e:pre CLI가 먼저 실행된다.
사전 실행 CLI는 docker-compose up -d로 docker-compose.yml을 기준으로 -d 백그라운드 컨테이너를 생성한다.
이 후 테스트 코드를 실행하게 된다.
테스트 코드가 끝나고 npm run test:e2e:done CLI가 호출되어 컨테이너가 down 된다!
가장 기본적인 테스트 데이터베이스 세팅할 수 있는 방법이다.
env 파일 내에 환경변수는 위 도커 파일 기준으로는 아래와 같이 세팅하면 된다.TEST_DB_HOST=localhost TEST_DB_USER=test TEST_DB_PORT=33306 TEST_DB_PASSWORD=test TEST_DB_DATABASE=wdietdb
테스트 코드에 대해 찾아 보다 테스트 시 DB 의존 처리 + 필요한 만큼 테스트 환경 만들기 유튜브 영상을 보게 되었다.
직전 영상에서는 유닛 테스트에 대한 생각을 나눠주셨고
위 링크는 추가로 나온 유닛 테스트 시 DB 의존을 어떻게 처리하는 지에 대해 생각을 나누어주신 영상이었다.
회사에서 테스트 코드에 대해 이야기를 나눌 때 공통으로 나눈 이야기가 DB와의 통신까지 테스트가 이루어 져야 되지 않겠냐 였다.
그렇기에 유닛 테스트보다 통합 테스트를 먼저 구현해 나가자는 결론을 내렸었다.
그 과정에서 TestContainer 구축 비용이나 Test DB Schema에 대한 고려는 없었다.
모두가 테스트 코드에 대해 지식이 완전하지 않아서 생각 자체를 나눌 수 없었던 부분이었다.
영상에서 가장 와닿았던 부분은 효율 및 현실과 공유 자원에 대한 이야기였다.
A: 테스트 성공 후 배포 예정
B: 그 사이 Test DB 스키마 변경 및 배포
A: Test 실패로 인한 배포 실패
--- 테스트 수행 속도 좋음 / 현실과 멈
mock
H2
TestContainer
rad-DB
--- 현실과 가까움 / 테스트 수행 속도 느림(비교적)
마지막 부분에서 WIFI가 끊기더라도 성공하는 테스트를 구현하는 것을 주요하게 생각하신다고 하셨다.
외부와 서버와 네트워킹이 필요한 테스트가 있다고 할 때 테스트 도중 네트워크가 불안정하여 테스트가 실패한다면 배포의 실패로도 연결된다.
<< 해당 의견도 상당히 설득력이 있었다.
내부 컨테이너로 말아 올리는 것에는 적용되지 않을 수 있지만 third-party API를 통해 데이터를 받아오는 경우라면 고려해야 하는 사항일 것 같았다.
이어지는 두 영상을 보며 테스트 코드 그 중 유닛테스트에 대한 새로운 관점을 갖게 된 시간이었다.
출근 후 해당 영상을 공유하며 의견을 다시 나누어 보는 시간을 가질 필요가 있을 것 같다 😀