그라운드 플립에선 다양한 쿼리문들이 존재하는 만큼 테스트가 필수적이다.
테스트는 외부에 의존적이면 안된다는 원칙이 있기에 보통 인메모리 db인 H2를 사용한다.
하지만 여기서 문제가 발생했다. 그라운드 플립은 MySQL에 의존적인 GIS 함수를 사용하기에 H2를 사용하지 못한다. 물론 H2에서 GIS 함수를 사용할 수 있는 H2GIS라는 확장판을 사용할 수 있지만 함수에서 미터 단위의 차이 등 일관되지 못한 환경이 구성된다.
또한 깃허브를 사용한 CI/CD 과정에서 테스트가 구동되기에 이 또한 만족시킬 수 있는 방법이 필요했다.
원격 DB 사용 (실패)
테스트만을 구동시키는 원격 RDS를 통해 테스트 환경을 구성하는 방법이다.
하지만 아래와 같은 이유들로 인해 사용하기 어려웠다.
팀원 모두 같은 스키마를 사용할 경우 테스트 과정에서 문제가 발생할 수 있다.
RDS 주소가 깃허브에 노출되지 않게 하기 어렵다.
testContainer 사용 (실패)
테스트 시 컨테이너를 띄워 독립된 테스트 환경을 보장하는 라이브러리이다.
설정도 크게 어렵지 않고 CI/CD 과정에서도 문제가 없지만, 로컬에서 클래스 단위로 테스트를 실행시킬 때마다 컨테이너를 띄워야하는 단점이 있다.
특히, 조사 결과 테스트가 매우 느려 불편하다는 단점이 존재했다.
로컬 MySQL 컨테이너 + Github Actions Setup MySQL (성공)
여러 방법을 찾아보다, CI/CD 호스트 머신에 MySQL을 직접 설치할 수 있다는 것을 알게되었다.
https://github.com/marketplace/actions/setup-mysql
위의 링크를 따라 적용 시 localhost로 접근이 가능해 로컬 환경과 test db의 uri도 동일하게 구성할 수 있었다.
우선 로컬에 같은 버전, 유저 정보를 가지는 MySQL 컨테이너를 띄운다.
version: '3'
services:
db:
image: mysql:8.0
container_name: mysql
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: root
TZ: Asia/Seoul
volumes:
- ./db/mysql/data:/var/lib/mysql
- ./db/mysql/init:/docker-entrypoint-initdb.d
platform: linux/x86_64
위의 사진과 같이 db, mysql, data, init 폴더만 만들어준다 (data 디렉토리 내부의 파일들은 무시한다)
application-test.yml을 작성한다.
spring:
config:
activate:
on-profile: test
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/groundflip_test
username: root
password: root
그리고 ci 과정에서 테스트할 때 MySQL 컨테이너를 띄우기 위해 깃헙 액션 스크립트를 수정한다.
name: BackEnd CI
on:
pull_request:
branches:
- develop
jobs:
build_and_test:
runs-on: ubuntu-20.04
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: 우분투 기본 MySQL 중지
run: sudo service mysql stop
- name: 테스트를 위한 MySQL 컨테이너 구동
uses: mirromutth/mysql-action@v1.1
with:
mysql version: '8.0'
mysql database: 'groundflip_test'
mysql root password: 'root'
mysql user: 'root'
--- 이하 생략
정상적으로 CI 과정이 진행되는 것을 확인했다. 소요 시간도 크게 오래걸리지 않는다.
GIS 자료형을 쓰게되면서 테스트 환경을 구현해야하는지 프로젝트 초반부터 고민이 많았다.
로컬 MySQL과 CI 과정의 MySQL 계정 정보를 일치시켜줘야 하는 단점이 있지만 여러 방면을 고려했을 때 최선인 것 같다.